major source structure and module name changes
This commit is contained in:
37
CASA-auth-token/server/ApacheSupport/2.2/Makefile.am
Normal file
37
CASA-auth-token/server/ApacheSupport/2.2/Makefile.am
Normal 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) *.h
|
||||
|
||||
.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
|
||||
|
||||
108
CASA-auth-token/server/ApacheSupport/2.2/README
Normal file
108
CASA-auth-token/server/ApacheSupport/2.2/README
Normal file
@@ -0,0 +1,108 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* README for mod_authn_casa
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
mod_authn_casa is an Apache 2.2 Basic Authentication Provider that
|
||||
can be configured to validate Basic Credentials carrying CASA
|
||||
Authentication Tokens.
|
||||
|
||||
Clients sending CASA Authentication Tokens as part of the Basic Credentials
|
||||
will format them in the following manner: "username:CasaAuthenticationToken",
|
||||
where the username is set to "CasaPrincipal" and the CasaAuthenticationToken
|
||||
is the token string obtained from the CASA Get Authentication Token API..
|
||||
|
||||
CONFIGURATION
|
||||
|
||||
To use mod_authn_casa as an authentication provider for a specific location
|
||||
you must first tell Apache that it must load the module, you do this by
|
||||
placing the module or a link to the module in the Apache server's modules
|
||||
folder and by placing the following line in the server's httpd.conf file:
|
||||
|
||||
LoadModule authn_casa_module modules/mod_authn_casa.so
|
||||
|
||||
The following lines show how Apache is configured to use mod_authn_casa
|
||||
for authenticating requests issued to mod_example:
|
||||
|
||||
<Location /example-info>
|
||||
SetHandler example-handler
|
||||
AuthType Basic
|
||||
AuthName "CASA-Authentication"
|
||||
AuthBasicProvider casa
|
||||
Require valid-user
|
||||
</Location>
|
||||
|
||||
Note that the name specified in the AuthName directive should match the name
|
||||
configured under CASA for the authentication realm used by CASA to obtain
|
||||
identity information for the service.
|
||||
|
||||
mod_authn_casa supports the following configuration directives:
|
||||
|
||||
UsernameCheck - This is a per-directory or per-location directive which
|
||||
configures whether or not mod_authn_casa must verify that
|
||||
the username is set to "CasaPrincipal". Possible values
|
||||
for this directive are 'on' or 'off'. Default is 'off'.
|
||||
|
||||
To enable UsernameChack for a particular location using
|
||||
CASA Authentication, include the following line inside
|
||||
the location configuration block:
|
||||
|
||||
UsernameCheck on
|
||||
|
||||
CLIENT PROGRAMMING NOTES
|
||||
|
||||
HTTP Clients sending requests to a location being protected by the CASA
|
||||
Authentication Provider must obtain an Authentication Token from the CASA
|
||||
Client for authenticating to the Service identified as the "location" being
|
||||
accessed in the HTTP Server. In the case of mod_example, the service name
|
||||
would be "example-info". Once the client obtains an Authentication Token
|
||||
from the CASA Client it must then include it in the HTTP Basic Authentication
|
||||
header that it must include in the HTTP Request. The HTTP Basic Authentication
|
||||
credentials should be in the following form:
|
||||
|
||||
Base64("CasaPrincipal":"AuthenticationToken")
|
||||
|
||||
SERVER PROGRAMMING NOTES
|
||||
|
||||
Apache modules being protected by the CASA Authentication Provider can obtain
|
||||
the following information about the authenticated identity:
|
||||
|
||||
username - This is accessed via the r->user variable or by examining the IdentityId
|
||||
environment variable associated with the request block. 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.
|
||||
|
||||
Name of the source of identity data (Authentication Realm) - This is accessed by
|
||||
examining the IdentityDataSourceName environment variable associated with the
|
||||
request block.
|
||||
|
||||
URL to the source of identity data - This is accessed by examining the
|
||||
IdentityDataSourceUrl environment variable associated with the request block.
|
||||
|
||||
Attributes of the authenticated identity - The attributes are set as environment
|
||||
variables associated with the request block. 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.
|
||||
|
||||
Note that environment variables are contained in the r->subprocess_env table.
|
||||
|
||||
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 HTTPS.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
13
CASA-auth-token/server/ApacheSupport/2.2/TODO
Normal file
13
CASA-auth-token/server/ApacheSupport/2.2/TODO
Normal file
@@ -0,0 +1,13 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* TODO for mod_authn_casa
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
This file contains a list of the items still outstanding for mod_authn_casa.
|
||||
|
||||
OUTSTANDING ITEMS
|
||||
|
||||
None.
|
||||
111
CASA-auth-token/server/ApacheSupport/2.2/linux/Makefile.am
Normal file
111
CASA-auth-token/server/ApacheSupport/2.2/linux/Makefile.am
Normal file
@@ -0,0 +1,111 @@
|
||||
#######################################################################
|
||||
#
|
||||
# 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)
|
||||
APACHEROOT = /home/jluciani/dev-local/apache2.2
|
||||
|
||||
# handle Mono secondary dependencies
|
||||
export MONO_PATH := $(MONO_PATH)
|
||||
|
||||
PLATFORMINDEPENDENTSOURCEDIR = ..
|
||||
PLATFORMDEPENDENTSOURCEDIR = .
|
||||
|
||||
MODULE_NAME = mod_authn_casa
|
||||
MODULE_EXT = so
|
||||
|
||||
CFILES = ../mod_authn_casa.c
|
||||
|
||||
CSFILES_CSC :=
|
||||
INCLUDES = -I. -I$(CASAROOT)/include -I$(APACHEROOT)/include
|
||||
RESOURCES =
|
||||
DEFINES = -Wno-format-extra-args -fno-strict-aliasing
|
||||
|
||||
CFLAGS += $(INCLUDES) $(DEFINES) -D_LARGEFILE64_SOURCE
|
||||
LIBS = -lpthread -lcasa_s_authtoken -lapr-1 -laprutil-1
|
||||
LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) -L$(CASALIBDIR)/$(TARGET_CFG) -L$(APACHEROOT)/lib -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
|
||||
|
||||
478
CASA-auth-token/server/ApacheSupport/2.2/mod_authn_casa.c
Normal file
478
CASA-auth-token/server/ApacheSupport/2.2/mod_authn_casa.c
Normal file
@@ -0,0 +1,478 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 <stdbool.h>
|
||||
|
||||
#include "apr_strings.h"
|
||||
#include "ap_config.h"
|
||||
#include "ap_provider.h"
|
||||
#include "httpd.h"
|
||||
#include "http_config.h"
|
||||
#include "http_core.h"
|
||||
#include "http_log.h"
|
||||
#include "http_protocol.h"
|
||||
#include "http_request.h"
|
||||
|
||||
#include "mod_auth.h"
|
||||
|
||||
#include "casa_s_authtoken.h"
|
||||
|
||||
//
|
||||
// Module per-dir configuration structure.
|
||||
//
|
||||
typedef struct _authn_casa_dir_cfg
|
||||
{
|
||||
int performUsernameCheck;
|
||||
|
||||
} authn_casa_dir_cfg;
|
||||
|
||||
|
||||
//
|
||||
// Forward declaration of our module structure.
|
||||
//
|
||||
module AP_MODULE_DECLARE_DATA authn_casa_module;
|
||||
|
||||
//
|
||||
// Environment variables set by module
|
||||
//
|
||||
static char CasaIdentityIdEnvVar[] = "IdentityId";
|
||||
static char CasaIdentitySourceNameEnvVar[] = "IdentityDataSourceName";
|
||||
static char CasaIdentitySourceUrlEnvVar[] = "IdentityDataSourceUrl";
|
||||
|
||||
//
|
||||
// Function: create_per_dir_config()
|
||||
//
|
||||
// Create per-dir configuration structure.
|
||||
//
|
||||
static void*
|
||||
create_per_dir_config(
|
||||
apr_pool_t *p,
|
||||
char *x)
|
||||
{
|
||||
authn_casa_dir_cfg *pDirConfig;
|
||||
|
||||
// Allocate space for our configuration structure
|
||||
pDirConfig = (authn_casa_dir_cfg*) apr_palloc(p, sizeof(*pDirConfig));
|
||||
|
||||
// Return our new configuration structure
|
||||
return (void*) pDirConfig;
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
* set_authn_casa_uname_check()
|
||||
*
|
||||
* Process UsernameCheck configuration directive..
|
||||
*
|
||||
* L2
|
||||
* ************************************************************************/
|
||||
static const char*
|
||||
set_authn_casa_uname_check(
|
||||
cmd_parms *cmd,
|
||||
void *cfg,
|
||||
int arg)
|
||||
{
|
||||
authn_casa_dir_cfg *pDirConfig = (authn_casa_dir_cfg*) cfg;
|
||||
|
||||
// Record the value in our structure
|
||||
pDirConfig->performUsernameCheck = arg;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Configuration directives array structure.
|
||||
//
|
||||
static const command_rec authn_casa_cmds[] =
|
||||
{
|
||||
AP_INIT_FLAG("UsernameCheck", // tbd - May be this directive should be on a per-directory or per-location basis
|
||||
set_authn_casa_uname_check,
|
||||
NULL,
|
||||
OR_AUTHCFG,
|
||||
"Check for username == CasaPrincipal (Value limited to 'on' or 'off')"),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
/* ************************************************************************
|
||||
* check_password()
|
||||
*
|
||||
* Given a user and password, expected to return AUTH_GRANTED if we
|
||||
* can validate the user/password combination.
|
||||
*
|
||||
* L2
|
||||
* ************************************************************************/
|
||||
static authn_status
|
||||
check_password(
|
||||
request_rec *r,
|
||||
const char *user,
|
||||
const char *password)
|
||||
{
|
||||
authn_status retStatus;
|
||||
authn_casa_dir_cfg *pDirConfig;
|
||||
bool userNameChecked = false;
|
||||
int i;
|
||||
char *pLocationName;
|
||||
|
||||
// First determine the length of the name of the location being protected
|
||||
i = 0;
|
||||
while (r->uri[i] != '\0')
|
||||
{
|
||||
if (r->uri[i] == '/')
|
||||
{
|
||||
// Ignore the slash if it is at the beginning of the uri
|
||||
if (i != 0)
|
||||
{
|
||||
// The slash is not at the beggining of the uri, stop.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
// Now get a copy of the location being protected
|
||||
if (i > 1)
|
||||
{
|
||||
pLocationName = apr_palloc(r->pool, i);
|
||||
if (pLocationName)
|
||||
{
|
||||
memset(pLocationName, 0, i);
|
||||
memcpy(pLocationName, &(r->uri[1]), i - 1); // Do not include the slashes
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Memory allocation failure");
|
||||
return AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are protecting the server root
|
||||
pLocationName = "apache_root";
|
||||
}
|
||||
|
||||
// Get access to our per-dir configuration structure
|
||||
pDirConfig = ap_get_module_config(r->per_dir_config,
|
||||
&authn_casa_module);
|
||||
if (pDirConfig)
|
||||
{
|
||||
// Assume success
|
||||
retStatus = AUTH_GRANTED;
|
||||
|
||||
// Check if we must perform the username check
|
||||
if (pDirConfig->performUsernameCheck != 0)
|
||||
{
|
||||
// Remember that we performed this check
|
||||
userNameChecked = true;
|
||||
|
||||
// Check if the username matches the name what we are expecting
|
||||
if (strcmp(user, "CasaPrincipal") != 0)
|
||||
{
|
||||
// The username does not match, allow other providers to get
|
||||
// a crack to it.
|
||||
retStatus = AUTH_USER_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the token if a problem has not been found
|
||||
if (retStatus == AUTH_GRANTED)
|
||||
{
|
||||
CasaStatus casaStatus;
|
||||
PrincipalIf *pPrincipalIf;
|
||||
|
||||
// Validate the token
|
||||
casaStatus = ValidateAuthToken(pLocationName,
|
||||
password,
|
||||
strlen(password),
|
||||
&pPrincipalIf);
|
||||
if (CASA_SUCCESS(casaStatus))
|
||||
{
|
||||
|
||||
int buffLen = 0;
|
||||
apr_table_t *e = r->subprocess_env;
|
||||
|
||||
// Associate necessary environment variables with the request block
|
||||
casaStatus = pPrincipalIf->getIdentityId(pPrincipalIf,
|
||||
NULL,
|
||||
&buffLen);
|
||||
if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
char *pBuff;
|
||||
|
||||
// Allocate buffer to obtain the Identity Id
|
||||
pBuff = apr_pcalloc(r->pool, buffLen);
|
||||
if (pBuff)
|
||||
{
|
||||
// Read the value into our buffer
|
||||
if (CASA_SUCCESS(pPrincipalIf->getIdentityId(pPrincipalIf,
|
||||
pBuff,
|
||||
&buffLen)))
|
||||
{
|
||||
// Now set the environment variable
|
||||
apr_table_setn(e, CasaIdentityIdEnvVar, pBuff);
|
||||
|
||||
// Also, update the username within the request block with the identity id
|
||||
r->user = pBuff;
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Unable to obtain identity id");
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Memory allocation failure");
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Un-expected error obtaining identity id, %08X", casaStatus);
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
if (retStatus == AUTH_GRANTED)
|
||||
{
|
||||
buffLen = 0;
|
||||
casaStatus = pPrincipalIf->getSourceName(pPrincipalIf,
|
||||
NULL,
|
||||
&buffLen);
|
||||
if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
char *pBuff;
|
||||
|
||||
// Allocate buffer to obtain the Identity Source Name
|
||||
pBuff = apr_pcalloc(r->pool, buffLen);
|
||||
if (pBuff)
|
||||
{
|
||||
// Read the value into our buffer
|
||||
if (CASA_SUCCESS(pPrincipalIf->getSourceName(pPrincipalIf,
|
||||
pBuff,
|
||||
&buffLen)))
|
||||
{
|
||||
// Now set the environment variable
|
||||
apr_table_setn(e, CasaIdentitySourceNameEnvVar, pBuff);
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Unable to obtain identity source name");
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Memory allocation failure");
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Un-expected error obtaining identity source name, %08X", casaStatus);
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (retStatus == AUTH_GRANTED)
|
||||
{
|
||||
buffLen = 0;
|
||||
casaStatus = pPrincipalIf->getSourceUrl(pPrincipalIf,
|
||||
NULL,
|
||||
&buffLen);
|
||||
if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
char *pBuff;
|
||||
|
||||
// Allocate buffer to obtain the Identity Source Url
|
||||
pBuff = apr_pcalloc(r->pool, buffLen);
|
||||
if (pBuff)
|
||||
{
|
||||
// Read the value into our buffer
|
||||
if (CASA_SUCCESS(pPrincipalIf->getSourceUrl(pPrincipalIf,
|
||||
pBuff,
|
||||
&buffLen)))
|
||||
{
|
||||
// Now set the environment variable
|
||||
apr_table_setn(e, CasaIdentitySourceUrlEnvVar, pBuff);
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Unable to obtain identity source url");
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Memory allocation failure");
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Un-expected error obtaining identity source url, %08X", casaStatus);
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (retStatus == AUTH_GRANTED)
|
||||
{
|
||||
char *pAttribNameBuff, *pAttribValueBuff;
|
||||
int enumHandle = 0;
|
||||
int attribNameBuffLen, attribValueBuffLen;
|
||||
|
||||
while (retStatus == AUTH_GRANTED)
|
||||
{
|
||||
// Get attribute lengths
|
||||
attribNameBuffLen = attribValueBuffLen = 0;
|
||||
casaStatus = pPrincipalIf->attributeEnumerate(pPrincipalIf,
|
||||
&enumHandle,
|
||||
NULL,
|
||||
&attribNameBuffLen,
|
||||
NULL,
|
||||
&attribValueBuffLen);
|
||||
if (CasaStatusCode(casaStatus) == CASA_STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
// Allocate buffers to obtain the attribute data
|
||||
pAttribNameBuff = apr_pcalloc(r->pool, attribNameBuffLen);
|
||||
pAttribValueBuff = apr_pcalloc(r->pool, attribValueBuffLen);
|
||||
if (pAttribNameBuff && pAttribValueBuff)
|
||||
{
|
||||
// Read the attribute into our buffer
|
||||
if (CASA_SUCCESS(pPrincipalIf->attributeEnumerate(pPrincipalIf,
|
||||
&enumHandle,
|
||||
pAttribNameBuff,
|
||||
&attribNameBuffLen,
|
||||
pAttribValueBuff,
|
||||
&attribValueBuffLen)))
|
||||
{
|
||||
// Now set the environment variable
|
||||
apr_table_setn(e, pAttribNameBuff, pAttribValueBuff);
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Unable to obtain identity attribute");
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Memory allocation failure");
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if we are done going through the attributes
|
||||
if (CasaStatusCode(casaStatus) == CASA_STATUS_NO_MORE_ENTRIES)
|
||||
{
|
||||
// Done
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Un-expected error during attribute enumeration, %08X", casaStatus);
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Release the principal interface instance
|
||||
pPrincipalIf->releaseReference(pPrincipalIf);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if the token validation failed for a CasaPrincipal
|
||||
if (userNameChecked)
|
||||
{
|
||||
// Token validation failed for a CasaPrincipal, always return AUTH_DENIED.
|
||||
retStatus = AUTH_DENIED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We did not check the username, set the return status based on the status
|
||||
// returned by ValidateAuthToken().
|
||||
if (CasaStatusCode(casaStatus) == CASA_STATUS_AUTHENTICATION_FAILURE)
|
||||
{
|
||||
// Authentication failed
|
||||
retStatus = AUTH_DENIED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allow other providers to get a crack to it
|
||||
retStatus = AUTH_USER_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ALERT, 0, r, "Did not get module per-server config structure");
|
||||
retStatus = AUTH_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
//
|
||||
// Authentication Provider Function Table
|
||||
//
|
||||
static const authn_provider authn_casa_provider =
|
||||
{
|
||||
&check_password,
|
||||
NULL, // We do not support Digest Authentication
|
||||
};
|
||||
|
||||
/* ************************************************************************
|
||||
* register_hooks()
|
||||
*
|
||||
* Register all of the module hooks.
|
||||
*
|
||||
* L2
|
||||
* ************************************************************************/
|
||||
static void
|
||||
register_hooks(
|
||||
apr_pool_t *p)
|
||||
{
|
||||
// Register as an authentication provider
|
||||
ap_register_provider(p,
|
||||
AUTHN_PROVIDER_GROUP, // Provider group
|
||||
"casa", // Provider name
|
||||
"0", // Provider version
|
||||
&authn_casa_provider); // Authentication Provider function table
|
||||
}
|
||||
|
||||
//
|
||||
// Declare ourselves to the HTTPD core.
|
||||
//
|
||||
module AP_MODULE_DECLARE_DATA authn_casa_module =
|
||||
{
|
||||
STANDARD20_MODULE_STUFF,
|
||||
create_per_dir_config, // Create per-dir config structures
|
||||
NULL, // merge per-dir config structures
|
||||
NULL, // Create per-server config structures
|
||||
NULL, // merge per-server config structures
|
||||
authn_casa_cmds, // command handlers
|
||||
register_hooks // register hooks
|
||||
};
|
||||
37
CASA-auth-token/server/ApacheSupport/Makefile.am
Normal file
37
CASA-auth-token/server/ApacheSupport/Makefile.am
Normal 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 = 2.2
|
||||
|
||||
DIST_SUBDIRS = 2.2
|
||||
|
||||
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
|
||||
|
||||
42
CASA-auth-token/server/AuthTokenSvc/.project
Normal file
42
CASA-auth-token/server/AuthTokenSvc/.project
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>CasaAuthServer</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.common.project.facet.core.builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jst.j2ee.ejb.annotations.xdoclet.xdocletbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
|
||||
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
<name>identity-abstraction.jar</name>
|
||||
<type>1</type>
|
||||
<location>/home/jluciani/dev-local/bandit/trunk/IdentityAbstraction/build/identity-abstraction.jar</location>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
||||
146
CASA-auth-token/server/AuthTokenSvc/Makefile.am
Normal file
146
CASA-auth-token/server/AuthTokenSvc/Makefile.am
Normal file
@@ -0,0 +1,146 @@
|
||||
#######################################################################
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
#######################################################################
|
||||
|
||||
SUBDIRS =
|
||||
DIST_SUBDIRS = src src/com src/com/novell src/com/novell/casa src/com/novell/casa/authtoksvc
|
||||
|
||||
EXTRA_DIST = $(JAVAFILES)
|
||||
|
||||
CASAROOT = ../../..
|
||||
|
||||
CASALIBDIR = $(CASAROOT)/$(LIB)
|
||||
|
||||
IDENT_ABSTRACTION_DIR = /home/jluciani/dev-local/bandit/trunk/IdentityAbstraction/build
|
||||
IDENT_ABSTRACTION_DEPENDANCIES_DIR = /home/jluciani/dev-local/bandit/trunk/commons/bin
|
||||
|
||||
JAVAROOT = .
|
||||
JAVAC= javac
|
||||
|
||||
WEBAPP_NAME = CasaAuthTokenSvc
|
||||
WEBAPP_EXT = war
|
||||
MODULE_NAME = CasaAuthToken
|
||||
MODULE_EXT = jar
|
||||
|
||||
JAVAFILES = src/com/novell/casa/authtoksvc/ProtoDefs.java \
|
||||
src/com/novell/casa/authtoksvc/AuthMechConfig.java \
|
||||
src/com/novell/casa/authtoksvc/SvcConfig.java \
|
||||
src/com/novell/casa/authtoksvc/IdenTokenConfig.java \
|
||||
src/com/novell/casa/authtoksvc/AuthTokenConfig.java \
|
||||
src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java \
|
||||
src/com/novell/casa/authtoksvc/AuthMechanism.java \
|
||||
src/com/novell/casa/authtoksvc/Authenticate.java \
|
||||
src/com/novell/casa/authtoksvc/RpcMethod.java \
|
||||
src/com/novell/casa/authtoksvc/Rpc.java \
|
||||
src/com/novell/casa/authtoksvc/GetAuthPolicy.java \
|
||||
src/com/novell/casa/authtoksvc/Base64Coder.java \
|
||||
src/com/novell/casa/authtoksvc/AuthReqMsg.java \
|
||||
src/com/novell/casa/authtoksvc/AuthRespMsg.java \
|
||||
src/com/novell/casa/authtoksvc/IdentityToken.java \
|
||||
src/com/novell/casa/authtoksvc/CasaIdentityToken.java \
|
||||
src/com/novell/casa/authtoksvc/AuthToken.java \
|
||||
src/com/novell/casa/authtoksvc/GetAuthPolicyReqMsg.java \
|
||||
src/com/novell/casa/authtoksvc/GetAuthPolicyRespMsg.java \
|
||||
src/com/novell/casa/authtoksvc/GetAuthToken.java \
|
||||
src/com/novell/casa/authtoksvc/GetAuthTokReqMsg.java \
|
||||
src/com/novell/casa/authtoksvc/GetAuthTokRespMsg.java \
|
||||
src/com/novell/casa/authtoksvc/Krb5Authenticate.java \
|
||||
src/com/novell/casa/authtoksvc/PwdAuthenticate.java \
|
||||
src/com/novell/casa/authtoksvc/SessionToken.java
|
||||
|
||||
BUILDDIR = build
|
||||
|
||||
WEBAPP = $(WEBAPP_NAME).$(WEBAPP_EXT)
|
||||
|
||||
#AUTHTOKEN_FILES = -C $(BUILDDIR)/webapp/WEB-INF/classes com/novell/casa/authtoksvc/AuthToken.class \
|
||||
# -C $(BUILDDIR)/webapp/WEB-INF/classes com/novell/casa/authtoksvc/AuthToken$SAXHandler.cless \
|
||||
# -C $(BUILDDIR)/webapp/WEB-INF/classes com/novell/casa/authtoksvc/AuthTokenConfig.class \
|
||||
# -C $(BUILDDIR)/webapp/WEB-INF/classes com/novell/casa/authtoksvc/AuthTokenConfig$SAXHandler.class \
|
||||
# -C $(BUILDDIR)/webapp/WEB-INF/classes com/novell/casa/authtoksvc/IdenTokenConfig.class \
|
||||
# -C $(BUILDDIR)/webapp/WEB-INF/classes com/novell/casa/authtoksvc/IdenTokenConfig$SAXHandler.class \
|
||||
# -C $(BUILDDIR)/webapp/WEB-INF/classes com/novell/casa/authtoksvc/IdentityToken.class \
|
||||
# -C $(BUILDDIR)/webapp/WEB-INF/classes com/novell/casa/authtoksvc/CasaIdentityToken.class \
|
||||
# -C $(BUILDDIR)/webapp/WEB-INF/classes com/novell/casa/authtoksvc/CasaIdentityToken$SAXHandler.class \
|
||||
# -C $(BUILDDIR)/webapp/WEB-INF/classes com/novell/casa/authtoksvc/Base64Coder.class
|
||||
AUTHTOKEN_FILES = -C $(BUILDDIR)/webapp/WEB-INF/classes com
|
||||
|
||||
CLASSES = $(addprefix $(BUILDDIR)/, $(JAVAFILES:%.java=%.class))
|
||||
|
||||
LIBS = /usr/share/java/servletapi5.jar
|
||||
CLASSPATH = $(IDENT_ABSTRACTION_DIR):$(LIBS)
|
||||
|
||||
CUR_DIR := $(shell pwd)
|
||||
|
||||
all: $(BUILDDIR)/$(WEBAPP) $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT)
|
||||
|
||||
$(BUILDDIR)/%.class: %.java
|
||||
@echo [======== Compiling $@ ========]
|
||||
$(JAVAC) -sourcepath src -classpath $(CLASSPATH) -d $(BUILDDIR)/webapp/WEB-INF/classes $<
|
||||
|
||||
$(BUILDDIR)/$(WEBAPP): $(BUILDDIR) $(CLASSES)
|
||||
@echo [======== Creating Webapp $@ ========]
|
||||
cp web.xml $(BUILDDIR)/webapp/WEB-INF/web.xml
|
||||
cp svc.settings $(BUILDDIR)/webapp/WEB-INF/conf/svc.settings
|
||||
cp authtoken.settings $(BUILDDIR)/webapp/WEB-INF/conf/authtoken.settings
|
||||
cp identoken.settings $(BUILDDIR)/webapp/WEB-INF/conf/identoken.settings
|
||||
cp src/com/novell/casa/authtoksvc/Krb5_mechanism.settings $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/Krb5Authenticate/mechanism.settings
|
||||
cp src/com/novell/casa/authtoksvc/Pwd_mechanism.settings $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/PwdAuthenticate/mechanism.settings
|
||||
cp $(IDENT_ABSTRACTION_DIR)/*.jar $(BUILDDIR)/webapp/WEB-INF/lib/
|
||||
cp $(IDENT_ABSTRACTION_DEPENDANCIES_DIR)/*.jar $(BUILDDIR)/webapp/WEB-INF/lib/
|
||||
jar cvf $(BUILDDIR)/$(WEBAPP) -C $(BUILDDIR)/webapp .
|
||||
cp $(BUILDDIR)/$(WEBAPP) $(CASALIBDIR)/java/
|
||||
|
||||
$(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT): $(BUILDDIR) $(CLASSES)
|
||||
@echo [======== Jarring $@ ========]
|
||||
jar cvf $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT) $(AUTHTOKEN_FILES)
|
||||
cp $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT) $(CASALIBDIR)/java/
|
||||
|
||||
$(BUILDDIR):
|
||||
[ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR)
|
||||
[ -d $(BUILDDIR)/webapp ] || mkdir -p $(BUILDDIR)/webapp
|
||||
[ -d $(BUILDDIR)/webapp/WEB-INF ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF
|
||||
[ -d $(BUILDDIR)/webapp/WEB-INF/classes ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/classes
|
||||
[ -d $(BUILDDIR)/webapp/WEB-INF/lib ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/lib
|
||||
[ -d $(BUILDDIR)/webapp/WEB-INF/conf ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf
|
||||
[ -d $(BUILDDIR)/webapp/WEB-INF/conf/enabled_services ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf/enabled_services
|
||||
[ -d $(BUILDDIR)/webapp/WEB-INF/conf/auth_mechanisms ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf/auth_mechanisms
|
||||
[ -d $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms
|
||||
[ -d $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/Krb5Authenticate ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/Krb5Authenticate
|
||||
[ -d $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/PwdAuthenticate ] || mkdir -p $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/PwdAuthenticate
|
||||
[ -d $(CASALIBDIR) ] || mkdir -p $(CASALIBDIR)
|
||||
[ -d $(CASALIBDIR)/java ] || mkdir -p $(CASALIBDIR)/java
|
||||
|
||||
install-exec-local:
|
||||
|
||||
uninstall-local:
|
||||
|
||||
#installcheck-local: install
|
||||
|
||||
clean-local:
|
||||
if [ -d $(BUILDDIR) ]; then rm -rf $(BUILDDIR); fi
|
||||
if [ -f $(CASALIBDIR)/java/$(MODULE_NAME).$(MODULE_EXT) ]; then rm -f $(CASALIBDIR)/java/$(MODULE_NAME).$(MODULE_EXT); fi
|
||||
if [ -f $(CASALIBDIR)/java/$(WEBAPP) ]; then rm -f $(CASALIBDIR)/java/$(WEBAPP); fi
|
||||
|
||||
distclean-local:
|
||||
|
||||
maintainer-clean-local:
|
||||
rm -f Makefile.in
|
||||
rm -f Makefile
|
||||
|
||||
292
CASA-auth-token/server/AuthTokenSvc/README
Normal file
292
CASA-auth-token/server/AuthTokenSvc/README
Normal file
@@ -0,0 +1,292 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* README for AuthTokenSvc
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
AuthTokenSvc is the CASA Authentication Token Service (ATS). It is implemented
|
||||
as a Java servlet and supporting classes that execute in the Tomcat environment.
|
||||
|
||||
The ATS is responsible for providing clients with the necessary authentication
|
||||
policy information, for authenticating client entities, and for providing
|
||||
clients with Authentication Tokens that they can then use for authenticating
|
||||
to CASA Authentication enabled services.
|
||||
|
||||
The ATS utilizes mechanism plug-ins for authenticating client entities as well
|
||||
Identity Token Providers for the generation of Identity Tokens.
|
||||
|
||||
ENVIRONMENT SETTINGS
|
||||
|
||||
The following options must be set in the JAVA_OPTS setting before starting Tomcat
|
||||
to allow the Kerberos authentication mechanism to work properly:
|
||||
|
||||
-Djavax.security.auth.useSubjectCredsOnly=false
|
||||
-Djava.security.auth.login.config={replace with the path for JAAS configuration
|
||||
file for the service}
|
||||
|
||||
After setting the above values in the JAVA_OPTS variable you must export it for
|
||||
Tomcat to be able to make use of it.
|
||||
|
||||
The following entry should be included in the JAAS configuration file specified
|
||||
in the java.security.auth.login.config option above to enable the Krb5 authentication
|
||||
mechanism to work correctly:
|
||||
|
||||
other {
|
||||
com.sun.security.auth.module.Krb5LoginModule required
|
||||
useTicketCache=true
|
||||
ticketCache="/var/cache/tomcat5/base/temp/ticket.cache"
|
||||
useKeyTab=true
|
||||
principal="host/server.company.com"
|
||||
doNotPrompt=true
|
||||
storeKey=true
|
||||
keyTab="/etc/krb5.keytab";
|
||||
}
|
||||
|
||||
Please adjust the ticketCache and principal setting to match your installation.
|
||||
|
||||
CONFIGURATION
|
||||
|
||||
AuthTokenSvc configuration consists of multiple entities. Most of the AuthTokenSvc
|
||||
configuration is contained within the "conf" folder under the WEB-INF folder of the
|
||||
application. For an example configuration setup for the AuthTokenSvc see the
|
||||
sampleConf folder.
|
||||
|
||||
The location of the AuthTokenSvc configuration folder can be over-ridden by specifying
|
||||
a different path via the com.novell.casa.authtoksvc.config system property.
|
||||
|
||||
CONFIGURING THE BASE SERVICE
|
||||
|
||||
The ATS base settings are configured in the svc.settings file under the conf folder.
|
||||
|
||||
Thhe following is an example svc.settings file:
|
||||
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<SessionTokenLifetime>43200</SessionTokenLifetime>
|
||||
<LifetimeShorter>10</LifetimeShorter>
|
||||
<IAConfigFile>/home/jluciani/jakarta-tomcat-5.0.28/webapps/CasaAuthTokenSvc/WEB-INF/conf/iaRealms.xml</IAConfigFile>
|
||||
<ReconfigureInterval>60</ReconfigureInterval>
|
||||
<startSearchContext>o=novell</startSearchContext>
|
||||
</settings>
|
||||
|
||||
Note the following about the sample svc.settings file:
|
||||
|
||||
- The settngs that you can specify in the svc.settings file are: SessionLifetime,
|
||||
LifetimeShorter, IAConfigFile, and startSearchContext.
|
||||
|
||||
- The SessionTokenLifetime setting specifies the number of seconds for which a
|
||||
session token is good for after being issued. The default value for this setting
|
||||
is 43200 seconds. Note that a larger value reduces overhead.
|
||||
|
||||
- The LifetimeShorter setting specifies the number of seconds that should be substracted
|
||||
from the SessionTokenLifetime when calculating the number of seconds that clients are
|
||||
told that the session tokens are good for. The default value for this setting is 5
|
||||
seconds.
|
||||
|
||||
- The IAConfigFile settings specifies the path to the identity abstraction
|
||||
configuration file. The identity abstraction configuration file configures
|
||||
the different realms (contexts) that the ATS can utilize to authenticate
|
||||
entities and resolve identities. In the future the configuration of this
|
||||
settng will be optional.
|
||||
|
||||
- The ReconfigureInterval setting specifies how often the ATS should refresh its
|
||||
configuration. The default value for this setting is 60 seconds. A ReconfigureInterval
|
||||
value of 0 means that the ATS will not refresh its configuration once it has been
|
||||
initialized, thus requiring that the servlet be re-initialized to make configuration
|
||||
changes take effect.
|
||||
|
||||
- The startSearchContext setting specifies the begin location for initiating
|
||||
context searches. The absence of this setting will result in searches ocurring
|
||||
from the root of the tree. This setting or an equivalent setting will be moved
|
||||
to the identity abstraction configuration file where it belongs. Once this is done,
|
||||
the setting will no longer be recognized within the svc.settings file.
|
||||
|
||||
CONFIGURING SERVICES TO CONSUME CASA AUTHENTICATION TOKENS
|
||||
|
||||
Services are configured to consume CASA authentication tokens by creating folders
|
||||
under the conf/enabled_services folders. Since CASA distinguishes between services
|
||||
of the same name existing in different hosts, the first folder that must be created
|
||||
is one for the host where the service resides. The host folder name must match the
|
||||
DNS name of the host where the service resides. Services are configured by creating
|
||||
a folder under the appropriate host folder with a name matching the service name.
|
||||
|
||||
Note when configuring services that the service name and the host names must match
|
||||
the service and host names specified by the client applications when requesting
|
||||
tokens to authenticate to them.
|
||||
|
||||
The services folder must contain an auth.policy file, an authtoken.settings file,
|
||||
and an identoken.settings file. In the absence of any one of those files, the ATS
|
||||
will default to utilizing the files present under its conf folder.
|
||||
|
||||
The auth.policy file specifies the authentication realms (or contexts) to which
|
||||
entities can authenticate to gain access to the service. The auth.policy file also
|
||||
specifies the authentication mechanisms that can be utilized to authenticate to the
|
||||
realms.
|
||||
|
||||
The following is an example auth.policy file:
|
||||
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<auth_policy>
|
||||
<auth_source>
|
||||
<realm>CorpTree</realm>
|
||||
<mechanism>Krb5Authenticate</mechanism>
|
||||
<mechanism_info>host@tokenserver.company.novell.com</mechanism_info>
|
||||
</auth_source>
|
||||
<auth_source>
|
||||
<realm>CorpTree</realm>
|
||||
<mechanism>PwdAuthenticate</mechanism>
|
||||
<mechanism_info></mechanism_info>
|
||||
</auth_source>
|
||||
</auth_policy>
|
||||
|
||||
Note the following about the sample auth.policy file:
|
||||
|
||||
- An authentication realm is specified in the auth.policy file by creating an
|
||||
auth_policy entry for it. An auth_policy entry must contain the realm name along
|
||||
with the entries for the authentication mechanisms.
|
||||
|
||||
- When a realm supports more than one authentication mechanism, you must create
|
||||
an auth_source entry for each supported mechanism.
|
||||
|
||||
- The realm names correspond to the realmIDs configured in the Identity Abstraction
|
||||
configuration file for the desired context entry.
|
||||
|
||||
- The authentication mechanism entries are: mechanism and mechanism_info. The mechanism
|
||||
entry specifies the name of the authentication mechanism. The mechanism_info specifies
|
||||
some mechanism specific information. Both authentication mechanism entries must be
|
||||
specified for an auth_source entry.
|
||||
|
||||
- The name of the Krb5 Authentication mechanism is "Krb5Authenticate". This mechanism
|
||||
requires that you specify the service's kerberos principal name under the mechanism_info
|
||||
key.
|
||||
|
||||
- The name of the username/password authentication mechanism is "PwdAuthenticate" and
|
||||
it does not require any information to be included under the mechanism_info key.
|
||||
|
||||
The authtoken.settings file contains settings that should be applied to authentication
|
||||
tokens issued to authenticate to the service.
|
||||
|
||||
The following is an example authtoken.settings file:
|
||||
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<TokenLifetime>3600</TokenLifetime>
|
||||
<LifetimeShorter>10</LifetimeShorter>
|
||||
<IdentityTokenType>CasaIdentityToken</IdentityTokenType>
|
||||
</settings>
|
||||
|
||||
Note the following about the sample authtoken.settings file:
|
||||
|
||||
- The settings that you can specify in the authtoken.settings file are: TokenLifetime,
|
||||
LifetimeShorter, and IdentityTokenType. If one of this tokens is not specified then
|
||||
its default value is utilized.
|
||||
|
||||
- The TokenLifetime setting specifies the number of seconds for which a token is good
|
||||
for after being issued. The default value for this setting is 3600 seconds. Note that
|
||||
a larger value reduces overhead, but it also gives more time for an intruder to
|
||||
utilize the token if it becomes compromized.
|
||||
|
||||
- The LifetimeShorter setting specifies the number of seconds that should be substracted
|
||||
from the TokenLifetime when calculating the number of seconds that clients are told
|
||||
that the tokens are good for. The default value for this setting is 5 seconds.
|
||||
|
||||
- The IdentityTokenType specifies the type of identity tokens that must be embedded in
|
||||
the authentication tokens with identity information. The default value for this
|
||||
setting is CasaIdentityToken.
|
||||
|
||||
The identoken.settings file contains settings that should be applied to identity tokens
|
||||
embedded in authentication tokens.
|
||||
|
||||
The following is an example identoken.settings file:
|
||||
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<Attributes>sn,groupMembership,guid</Attributes>
|
||||
<EncryptAttributes>false</EncryptAttributes>
|
||||
<Certificate>Base64 encoded certificate</Certificate>
|
||||
</settings>
|
||||
|
||||
Note the following about the sample identoken.settings file:
|
||||
|
||||
- The settings that you can specify in the identoken.settings file are: Attributes.
|
||||
EncryptAttributes, and Certificate.
|
||||
|
||||
- The Attributes setting specifies the identity attributes that must be included
|
||||
as part of the identity token, The attributes are specified in the form of a coma
|
||||
delimited list. The default velue for this setting is "sn".
|
||||
|
||||
- The EncryptAtributes setting specifies whether or not the identity information
|
||||
contained in the identity token should be emcrypted with the services's Public
|
||||
Certificate. The default value for this setting is "false". Please note that
|
||||
to enable identity attribute encryption you must not allow the ATS to default to
|
||||
the file present in its conf folder (Attribute encryption is not yet supported
|
||||
by the Casa identity token provider).
|
||||
|
||||
- The Certificate setting specifies the certificate that must be utilized to encrypt
|
||||
identity attribute data. The certificate contains the public key of the targeted
|
||||
service. The certificate data is Base64 encoded.
|
||||
|
||||
- The identoken.settings file can also contain additional identity token provider
|
||||
specific settings.
|
||||
|
||||
CONFIGURING AUTHENTICATION MECHANISMS
|
||||
|
||||
Authentication mechanisms available to the AuthTokenSvc are configured by creating
|
||||
a sub-folder named after the authentication mechanism type under the
|
||||
conf/auth_mechanisms folder. The authentication mechanism folders must contain a
|
||||
settings file named mechanism.settings. The mechanism.settings file must contain the
|
||||
name of the class implementing the mechanism along with path information which
|
||||
can be utilized by the ATS to load the class. The mechanism.settings file can
|
||||
also contain mechanism specific settings.
|
||||
|
||||
The following setting is mandatory:
|
||||
|
||||
ClassName - This is the name of the class implementing the authentication mechanism.
|
||||
|
||||
One of the following settings must be included:
|
||||
|
||||
RelativeClassPath - This is a relative path from the web application's root folder
|
||||
to the folder containing the class implementing the mechanism.
|
||||
|
||||
ClassPath - This is an absolute path to the folder containing the path to the class
|
||||
implementing the mechanism.
|
||||
|
||||
The following is an example mechanism.settings file for the Krb5Authentication
|
||||
mechanism:
|
||||
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<ClassName>com.novell.casa.authtoksvc.Krb5Authenticate</ClassName>
|
||||
<RelativeClassPath>WEB-INF/classes</RelativeClassPath>
|
||||
<ServicePrincipalName>host@authtokenserver.company.com</ServicePrincipalName>
|
||||
</settings>
|
||||
|
||||
The base AuthTokenSvc package contains two authentication mechanisms, these are
|
||||
Krb5Authenticate and PwdAuthenticate. The configuration under sampleConf is set up
|
||||
to allow an AuthTokenSvc to leverage both mechanisms.
|
||||
|
||||
The Krb5Authenticate mechanism requires that the following setting also be included
|
||||
in its mechanism.settings file:
|
||||
|
||||
ServicePrincipalName - This is the name of the Kerberos Service Principal that the
|
||||
Authentication Token Service runs as when authenticating other entities.
|
||||
|
||||
CONFIGURING ADDITIONAL IDENTITY TOKEN PROVIDERS
|
||||
|
||||
- TBD -
|
||||
|
||||
SECURITY CONSIDERATIONS
|
||||
|
||||
- TBD -
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
21
CASA-auth-token/server/AuthTokenSvc/TODO
Normal file
21
CASA-auth-token/server/AuthTokenSvc/TODO
Normal file
@@ -0,0 +1,21 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* TODO for AuthTokenSvc
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
This file contains a list of the items still outstanding for AuthTokenSvc.
|
||||
|
||||
OUTSTANDING ITEMS
|
||||
|
||||
- Switch to a Web Services model where the Client/Server protocol uses SOAP.
|
||||
- Switch to use WS-Security, WS-Policy, and WS-Conversation for Authentication Tokens and Session Tokens.
|
||||
- Add code to verify that client/server communications occur over HTTPS.
|
||||
- Add logging.
|
||||
- Create plug-in API for Identity Token Providers.
|
||||
- Integrate into CASA build environment.
|
||||
- Review Code.
|
||||
- Change printfs used for debugging into a suitable mechanism.
|
||||
|
||||
4
CASA-auth-token/server/AuthTokenSvc/authtoken.settings
Normal file
4
CASA-auth-token/server/AuthTokenSvc/authtoken.settings
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<TokenLifetime>3600</TokenLifetime>
|
||||
</settings>
|
||||
6
CASA-auth-token/server/AuthTokenSvc/identoken.settings
Normal file
6
CASA-auth-token/server/AuthTokenSvc/identoken.settings
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<EncryptAttributes>false</EncryptAttributes>
|
||||
<Attributes>sn</Attributes>
|
||||
</settings>
|
||||
|
||||
13
CASA-auth-token/server/AuthTokenSvc/sampleConf/auth.policy
Normal file
13
CASA-auth-token/server/AuthTokenSvc/sampleConf/auth.policy
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<auth_policy>
|
||||
<auth_source>
|
||||
<realm>CorpTree</realm>
|
||||
<mechanism>Krb5Authenticate</mechanism>
|
||||
<mechanism_info>host@authtokenserver.company.com</mechanism_info>
|
||||
</auth_source>
|
||||
<auth_source>
|
||||
<realm>CorpTree</realm>
|
||||
<mechanism>PwdAuthenticate</mechanism>
|
||||
<mechanism_info></mechanism_info>
|
||||
</auth_source>
|
||||
</auth_policy>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<ClassName>com.novell.casa.authtoksvc.Krb5Authenticate</ClassName>
|
||||
<RelativeClassPath>WEB-INF/classes</RelativeClassPath>
|
||||
<ServicePrincipalName>host@tokenserver.company.novell.com</ServicePrincipalName>
|
||||
</settings>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<ClassName>com.novell.casa.authtoksvc.PwdAuthenticate</ClassName>
|
||||
<RelativeClassPath>WEB-INF/classes</RelativeClassPath>
|
||||
</settings>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<TokenLifetime>3600</TokenLifetime>
|
||||
</settings>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<auth_policy>
|
||||
<auth_source>
|
||||
<realm>CorpTree</realm>
|
||||
<mechanism>Krb5Authenticate</mechanism>
|
||||
<mechanism_info>host@tokenserver.company.novell.com</mechanism_info>
|
||||
</auth_source>
|
||||
<auth_source>
|
||||
<realm>CorpTree</realm>
|
||||
<mechanism>PwdAuthenticate</mechanism>
|
||||
<mechanism_info></mechanism_info>
|
||||
</auth_source>
|
||||
</auth_policy>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<TokenLifetime>3600</TokenLifetime>
|
||||
</settings>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<EncryptAttributes>false</EncryptAttributes>
|
||||
<Attributes>sn,groupMembership</Attributes>
|
||||
</settings>
|
||||
|
||||
25
CASA-auth-token/server/AuthTokenSvc/sampleConf/iaRealms.xml
Normal file
25
CASA-auth-token/server/AuthTokenSvc/sampleConf/iaRealms.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<bci:realms
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:bci="http://www.bandit-project.org/commonidentity"
|
||||
xmlns:xacml="urn:oasis:names:tc:xacml:2.0:policy:schema:os"
|
||||
xsi:schemaLocation="urn:oasis:names:tc:xacml:2.0:policy:schema:os:access_control-xacml-2.0-policy-schema-os.xsd">
|
||||
<bci:realm
|
||||
desc="My Corporate Directory"
|
||||
connectorType="org.bandit.ia.connectors.LDAPConnectorInitialCtxFactory"
|
||||
id="jctree">
|
||||
<bci:connection xsi:type="bci:LDAPConnector">
|
||||
<bci:address>ldap://dirserver.companyname.com:389</bci:address>
|
||||
<bci:security>
|
||||
<bci:authentication>simple</bci:authentication>
|
||||
<bci:principal>cn=admin,o=companyname</bci:principal>
|
||||
<bci:credentials>password</bci:credentials>
|
||||
</bci:security>
|
||||
</bci:connection>
|
||||
</bci:realm>
|
||||
<bci:realm desc="Realm Join Definition" id="E263CCC1-8F9D-4551-B786-068AA84E8564">
|
||||
<bci:connection xsi:type="bci:JoinConnector">
|
||||
<bci:realmID>CorpTree</bci:realmID>
|
||||
</bci:connection>
|
||||
</bci:realm>
|
||||
</bci:realms>
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<EncryptAttributes>false</EncryptAttributes>
|
||||
<Attributes>sn</Attributes>
|
||||
</settings>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<IAConfigFile>/home/jluciani/jakarta-tomcat-5.0.28/webapps/CasaAuthTokenSvc/WEB-INF/conf/iaRealms.xml</IAConfigFile>
|
||||
<SessionTokenLifetime>43200</SessionTokenLifetime>
|
||||
</settings>
|
||||
@@ -0,0 +1,258 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
* AuthMechConfig Class.
|
||||
*
|
||||
* This class obtains and maintains authentication token configuration.
|
||||
*
|
||||
*/
|
||||
public class AuthMechConfig
|
||||
{
|
||||
// Well known authentication token configuration settings
|
||||
public final static String ClassName = "ClassName";
|
||||
public final static String RelativeClassPath = "RelativeClassPath";
|
||||
public final static String ClassPath = "ClassPath";
|
||||
|
||||
private Map m_mechSettingsMap;
|
||||
|
||||
/*
|
||||
* Class for handling parsing events.
|
||||
*/
|
||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
||||
{
|
||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
||||
private final static int AWAITING_SETTING_ELEMENT_START = 1;
|
||||
private final static int AWAITING_SETTING_ELEMENT_DATA = 2;
|
||||
private final static int AWAITING_SETTING_ELEMENT_END = 3;
|
||||
private final static int DONE_PARSING = 4;
|
||||
|
||||
private final static String m_rootElementName = "settings";
|
||||
|
||||
private Map m_keyMap;
|
||||
private int m_state;
|
||||
private String m_currentKey;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SAXHandler(Map keyMap)
|
||||
{
|
||||
super();
|
||||
|
||||
// Initialize our members
|
||||
m_keyMap = keyMap;
|
||||
m_state = AWAITING_ROOT_ELEMENT_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* endDocument() implementation.
|
||||
*/
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
// Verify that we are not in an invalid state
|
||||
if (m_state != DONE_PARSING)
|
||||
{
|
||||
System.err.println("AuthMechConfig SAXHandler.endDocument()- Invalid state" + m_state);
|
||||
throw new SAXException("Invalid state at endDocument");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* startElement() implementation.
|
||||
*/
|
||||
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
case AWAITING_ROOT_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (m_rootElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthMechConfig SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SETTING_ELEMENT_START:
|
||||
// Keep track of the key name
|
||||
m_currentKey = qName;
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_DATA;
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("AuthMechConfig SAXHandler.startElement()- Invalid state " + m_state);
|
||||
throw new SAXException("Invalid state at startElement");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endElement() immplementation.
|
||||
*/
|
||||
public void endElement (String uri, String name, String qName) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
case AWAITING_SETTING_ELEMENT_DATA:
|
||||
case AWAITING_SETTING_ELEMENT_END:
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_START;
|
||||
break;
|
||||
|
||||
case AWAITING_SETTING_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (m_rootElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = DONE_PARSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthMechConfig SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("AuthMechConfig SAXHandler.endElement()- Invalid state " + m_state);
|
||||
throw new SAXException("Invalid state at endElement");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* character() implementation.
|
||||
*/
|
||||
public void characters (char ch[], int start, int length) throws SAXException
|
||||
{
|
||||
// Consume the data if in the right state
|
||||
if (m_state == AWAITING_SETTING_ELEMENT_DATA)
|
||||
{
|
||||
// Consume the data and add the key to map
|
||||
m_keyMap.put(m_currentKey, new String(ch, start, length));
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor which sets default configuration values.
|
||||
*/
|
||||
public AuthMechConfig() throws Exception
|
||||
{
|
||||
System.err.println("AuthMechConfig()- Default");
|
||||
|
||||
// Create a map to keep track of the token settings
|
||||
m_mechSettingsMap = new HashMap();
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public AuthMechConfig(String mechSettingsFileName) throws Exception
|
||||
{
|
||||
System.err.println("AuthMechConfig()-");
|
||||
|
||||
// Create a map to keep track of the token settings
|
||||
m_mechSettingsMap = new HashMap();
|
||||
|
||||
try
|
||||
{
|
||||
// Get an input stream to read from the token settings file
|
||||
File f = new File(mechSettingsFileName);
|
||||
FileInputStream inStream = new FileInputStream(f);
|
||||
|
||||
// Parse the file
|
||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
||||
SAXHandler handler = new SAXHandler(m_mechSettingsMap);
|
||||
xr.setContentHandler(handler);
|
||||
xr.setErrorHandler(handler);
|
||||
|
||||
InputSource source = new InputSource(inStream);
|
||||
xr.parse(source);
|
||||
|
||||
inStream.close();
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
System.err.println("AuthMechConfig()- " + mechSettingsFileName + " format error, exception: " + e.toString());
|
||||
throw new Exception("AuthMechConfig()- authtoken.settings format error");
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("AuthMechConfig()- SecurityException accessing " + mechSettingsFileName + " Exception=" + e.toString());
|
||||
throw new Exception("AuthMechConfig()- Not able to access file");
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
System.err.println("AuthMechConfig()- File " + mechSettingsFileName + " not found");
|
||||
throw new Exception("AuthMechConfig()- File not found");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println("AuthMechConfig()- IOException accessing " + mechSettingsFileName + " Exception=" + e.toString());
|
||||
throw new Exception("AuthMechConfig()- Read error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the value associated with the specified setting.
|
||||
*/
|
||||
public String getSetting(String settingName) throws Exception
|
||||
{
|
||||
// Try to find the setting in our map
|
||||
String value = (String) m_mechSettingsMap.get(settingName);
|
||||
if (value == null)
|
||||
{
|
||||
System.err.println("AuthMechConfig.getSetting()- Did not find setting " + settingName);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthMechConfig.getSetting()- Found setting " + settingName);
|
||||
System.err.println("AuthMechConfig.getSetting()- Setting value = " + value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
/*
|
||||
* AuthMechanism Interface.
|
||||
*
|
||||
* This is the interface implemented by Authentication Mechanisms.
|
||||
*
|
||||
* Please note that Authentication Machanisms must also implement the
|
||||
* Serializable interface.
|
||||
*
|
||||
*/
|
||||
public interface AuthMechanism
|
||||
{
|
||||
/*
|
||||
* Initialize the authentication mechanism.
|
||||
*/
|
||||
void init(SvcConfig svcConfig, AuthMechConfig mechConfig) throws Exception;
|
||||
|
||||
/*
|
||||
* Process authenticate request. If successful, return the Id of the
|
||||
* authenticated identity.
|
||||
*/
|
||||
String invoke(AuthReqMsg authReqMsg) throws Exception;
|
||||
|
||||
/*
|
||||
* Return the mechanism id.
|
||||
*/
|
||||
String getId();
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
|
||||
/**
|
||||
* AuthReqMsg Class.
|
||||
*
|
||||
* This class deals with the message sent by Casa Client when requesting
|
||||
* that an entity be authenticated. The format of the message is as
|
||||
* follows:
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <auth_req>
|
||||
* <realm>realm value</realm>
|
||||
* <mechanism>mechanism id</mechanism>
|
||||
* <auth_mech_token>mechanism token data</auth_mech_token>
|
||||
* </auth_req>
|
||||
*
|
||||
*/
|
||||
public class AuthReqMsg
|
||||
{
|
||||
|
||||
protected String m_realm = null;
|
||||
protected String m_authMechToken = null;
|
||||
protected String m_authMechanism = null;
|
||||
|
||||
/*
|
||||
* Class for handling Authentication Request parsing events.
|
||||
*/
|
||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
||||
{
|
||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
||||
private final static int AWAITING_ROOT_ELEMENT_END = 1;
|
||||
private final static int AWAITING_REALM_ELEMENT_START = 2;
|
||||
private final static int AWAITING_REALM_ELEMENT_END = 3;
|
||||
private final static int AWAITING_REALM_DATA = 4;
|
||||
private final static int AWAITING_MECH_ELEMENT_START = 5;
|
||||
private final static int AWAITING_MECH_ELEMENT_END = 6;
|
||||
private final static int AWAITING_MECH_DATA = 7;
|
||||
private final static int AWAITING_AUTH_MECH_TOKEN_ELEMENT_START = 8;
|
||||
private final static int AWAITING_AUTH_MECH_TOKEN_ELEMENT_END = 9;
|
||||
private final static int AWAITING_AUTH_MECH_TOKEN_DATA = 10;
|
||||
private final static int DONE_PARSING = 11;
|
||||
|
||||
private AuthReqMsg m_authReqMsg;
|
||||
private int m_state;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SAXHandler (AuthReqMsg authReqMsg)
|
||||
{
|
||||
super();
|
||||
|
||||
// Initialize our members
|
||||
m_authReqMsg = authReqMsg;
|
||||
m_state = AWAITING_ROOT_ELEMENT_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* endDocument() implementation.
|
||||
*/
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
// Verify that we obtained all of the required elements
|
||||
if (m_state != DONE_PARSING)
|
||||
{
|
||||
System.err.println("AuthReqMsg SAXHandler.endDocument()- Missing element");
|
||||
throw new SAXException("Missing element");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* startElement() implementation.
|
||||
*/
|
||||
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
case AWAITING_ROOT_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.authRequestElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_REALM_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_REALM_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.realmElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_REALM_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_MECH_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.mechanismElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_MECH_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_AUTH_MECH_TOKEN_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.authMechTokenElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_AUTH_MECH_TOKEN_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("AuthReqMsg SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endElement() immplementation.
|
||||
*/
|
||||
public void endElement (String uri, String name, String qName) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
case AWAITING_ROOT_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.authRequestElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = DONE_PARSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_REALM_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.realmElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_MECH_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_MECH_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.mechanismElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_AUTH_MECH_TOKEN_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_AUTH_MECH_TOKEN_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.authMechTokenElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ROOT_ELEMENT_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("AuthReqMsg SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* character() implementation.
|
||||
*/
|
||||
public void characters (char ch[], int start, int length) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
case AWAITING_REALM_DATA:
|
||||
// Consume the data
|
||||
m_authReqMsg.m_realm = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_REALM_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_MECH_DATA:
|
||||
// Consume the data
|
||||
m_authReqMsg.m_authMechanism = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_MECH_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_AUTH_MECH_TOKEN_DATA:
|
||||
// Consume the data
|
||||
m_authReqMsg.m_authMechToken = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_AUTH_MECH_TOKEN_ELEMENT_END;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public AuthReqMsg (InputStream inStream) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse the AuthReqMsg
|
||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
||||
SAXHandler handler = new SAXHandler(this);
|
||||
xr.setContentHandler(handler);
|
||||
xr.setErrorHandler(handler);
|
||||
|
||||
InputSource source = new InputSource(inStream);
|
||||
xr.parse(source);
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
System.err.println("AuthReqMsg()- Parse exception: " + e.toString());
|
||||
throw new Exception("Protocol error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to get the authentication realm.
|
||||
*/
|
||||
public String getRealm() throws Exception
|
||||
{
|
||||
return m_realm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to get the authentication mechanism token.
|
||||
*/
|
||||
public String getAuthMechToken() throws Exception
|
||||
{
|
||||
return m_authMechToken;
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to get the authentication mechanism id.
|
||||
*/
|
||||
public String getMechanismId() throws Exception
|
||||
{
|
||||
return m_authMechanism;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
/**
|
||||
* AuthRespMsg Class.
|
||||
*
|
||||
* This class deals with the message sent to the CASA Client as a
|
||||
* response to an authentication request. The format of the message is
|
||||
* as follows when the response includes a session token:
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <auth_resp>
|
||||
* <status><description>OK</description>200</status>
|
||||
* <session_token><lifetime>lifetime value</lifetime>session token data</session_token>
|
||||
* </auth_resp>
|
||||
*
|
||||
* The format of the message is as follows when the response does not
|
||||
* include a session token.
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <auth_resp>
|
||||
* <status><description>status description</description>status code</status>
|
||||
* </auth_resp>
|
||||
*
|
||||
* Plase note that the protocol utilizes the status codes defined
|
||||
* in the HTTP 1.1 Specification.
|
||||
*
|
||||
*/
|
||||
public class AuthRespMsg
|
||||
{
|
||||
|
||||
String m_msg;
|
||||
|
||||
/*
|
||||
* Constructor for a msg that does not include the session token.
|
||||
*/
|
||||
public AuthRespMsg (
|
||||
String statusDescription,
|
||||
String statusCode) throws Exception
|
||||
{
|
||||
// Get a StringBuffer to help us with the construction of the message
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
// Start building the message
|
||||
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
|
||||
sb.append("<" + ProtoDefs.authResponseElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.statusElementName + ">"
|
||||
+ "<" + ProtoDefs.descriptionElementName + ">" + statusDescription + "</" + ProtoDefs.descriptionElementName + ">"
|
||||
+ statusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
|
||||
sb.append("</" + ProtoDefs.authResponseElementName + ">" + "\r\n");
|
||||
|
||||
// The message has now been built, save it.
|
||||
m_msg = sb.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor for a msg that includes the session token.
|
||||
*/
|
||||
public AuthRespMsg (
|
||||
String statusDescription,
|
||||
String statusCode,
|
||||
String sessionToken,
|
||||
String sessionTokenLifetime) throws Exception
|
||||
{
|
||||
// Get a StringBuffer to help us with the construction of the message
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
// Start building the message
|
||||
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
|
||||
sb.append("<" + ProtoDefs.authResponseElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.statusElementName + ">"
|
||||
+ "<" + ProtoDefs.descriptionElementName + ">" + ProtoDefs.httpOkStatusMsg + "</" + ProtoDefs.descriptionElementName + ">"
|
||||
+ ProtoDefs.httpOkStatusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.sessionTokenElementName + ">"
|
||||
+ "<" + ProtoDefs.lifetimeElementName + ">" + sessionTokenLifetime + "</" + ProtoDefs.lifetimeElementName + ">"
|
||||
+ sessionToken + "</" + ProtoDefs.sessionTokenElementName + ">" + "\r\n");
|
||||
sb.append("</" + ProtoDefs.authResponseElementName + ">" + "\r\n");
|
||||
|
||||
// The message has now been built, save it.
|
||||
m_msg = sb.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containing the AuthRespMsg.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return m_msg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,466 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
|
||||
/*
|
||||
* AuthToken Class.
|
||||
*
|
||||
* This class constructs authentication tokens that clients can present
|
||||
* to services for authentication. The format of the authentication token
|
||||
* is as follows:
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <auth_token>
|
||||
* <signature>signature value</signature>
|
||||
* <lifetime>lifetime value</lifetime>
|
||||
* <ident_token><type>Identity Token type</type>identity token data</ident_token>
|
||||
* </auth_token>
|
||||
*
|
||||
*/
|
||||
public class AuthToken
|
||||
{
|
||||
|
||||
private String m_token;
|
||||
private String m_lifetime;
|
||||
private String m_lifetimeShorter;
|
||||
private String m_identityTokenType;
|
||||
private StringBuffer m_identityToken;
|
||||
private String m_signature;
|
||||
|
||||
/*
|
||||
* Class for handling parsing events.
|
||||
*/
|
||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
||||
{
|
||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
||||
private final static int AWAITING_ROOT_ELEMENT_END = 1;
|
||||
private final static int AWAITING_SIGNATURE_ELEMENT_START = 2;
|
||||
private final static int AWAITING_SIGNATURE_ELEMENT_END = 3;
|
||||
private final static int AWAITING_SIGNATURE_DATA = 4;
|
||||
private final static int AWAITING_LIFETIME_ELEMENT_START = 5;
|
||||
private final static int AWAITING_LIFETIME_ELEMENT_END = 6;
|
||||
private final static int AWAITING_LIFETIME_DATA = 7;
|
||||
private final static int AWAITING_IDENT_TOKEN_ELEMENT_START = 8;
|
||||
private final static int AWAITING_IDENT_TOKEN_ELEMENT_END = 9;
|
||||
private final static int AWAITING_IDENT_TOKEN_DATA = 10;
|
||||
private final static int AWAITING_TYPE_ELEMENT_START = 11;
|
||||
private final static int AWAITING_TYPE_ELEMENT_END = 12;
|
||||
private final static int AWAITING_TYPE_DATA = 13;
|
||||
private final static int DONE_PARSING = 14;
|
||||
|
||||
private AuthToken m_AuthToken;
|
||||
private int m_state;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SAXHandler (AuthToken AuthToken)
|
||||
{
|
||||
super();
|
||||
|
||||
// Initialize our members
|
||||
m_AuthToken = AuthToken;
|
||||
m_state = AWAITING_ROOT_ELEMENT_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* endDocument() implementation.
|
||||
*/
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
// Verify that we obtained all of the required elements
|
||||
if (m_state != DONE_PARSING)
|
||||
{
|
||||
System.err.println("AuthToken SAXHandler.endDocument()- Missing element");
|
||||
throw new SAXException("Missing element");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* startElement() implementation.
|
||||
*/
|
||||
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_ROOT_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.authTokenElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SIGNATURE_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SIGNATURE_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.signatureElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SIGNATURE_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_LIFETIME_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.lifetimeElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_LIFETIME_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AWAITING_IDENT_TOKEN_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.identTokenElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_TYPE_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_TYPE_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.typeElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_TYPE_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("AuthToken SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endElement() immplementation.
|
||||
*/
|
||||
public void endElement (String uri, String name, String qName) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_ROOT_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.authTokenElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = DONE_PARSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SIGNATURE_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.signatureElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_LIFETIME_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_LIFETIME_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.lifetimeElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_IDENT_TOKEN_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_TYPE_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.typeElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_IDENT_TOKEN_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_IDENT_TOKEN_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.identTokenElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ROOT_ELEMENT_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("AuthToken SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* character() implementation.
|
||||
*/
|
||||
public void characters (char ch[], int start, int length) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_SIGNATURE_DATA:
|
||||
// Consume the data
|
||||
m_AuthToken.m_signature = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SIGNATURE_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_LIFETIME_DATA:
|
||||
// Consume the data
|
||||
m_AuthToken.m_lifetime = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_LIFETIME_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_TYPE_DATA:
|
||||
// Consume the data
|
||||
m_AuthToken.m_identityTokenType = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_TYPE_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_IDENT_TOKEN_DATA:
|
||||
case AWAITING_IDENT_TOKEN_ELEMENT_END:
|
||||
// Consume the data
|
||||
m_AuthToken.m_identityToken.append(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_IDENT_TOKEN_ELEMENT_END;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public AuthToken(String identityId,
|
||||
String realm,
|
||||
String targetService,
|
||||
String targetHost,
|
||||
SvcConfig svcConfig,
|
||||
EnabledSvcsConfig enabledSvcsConfig) throws Exception
|
||||
{
|
||||
// Get access to the authentication token configuration for this service
|
||||
AuthTokenConfig authTokenConfig = enabledSvcsConfig.getAuthTokenConfig(targetHost, targetService);
|
||||
if (authTokenConfig != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// For now lets use the services of the only IdentityToken provider
|
||||
// that we have.
|
||||
//
|
||||
// tbd - Add code to allow for the consumption of tokens
|
||||
// from different providers.
|
||||
CasaIdentityToken identityToken = new CasaIdentityToken(enabledSvcsConfig.getIdenTokenConfig(targetHost, targetService));
|
||||
identityToken.initialize(identityId,
|
||||
realm,
|
||||
targetService,
|
||||
targetHost,
|
||||
svcConfig);
|
||||
|
||||
m_identityToken = new StringBuffer();
|
||||
m_identityToken.append(identityToken.getEncodedToken());
|
||||
m_identityTokenType = identityToken.getProviderType();
|
||||
|
||||
m_lifetime = authTokenConfig.getSetting(AuthTokenConfig.TokenLifetime);
|
||||
m_lifetimeShorter = authTokenConfig.getSetting(AuthTokenConfig.LifetimeShorter);
|
||||
|
||||
// Generate a signature
|
||||
// tbd - Over identToken, identToken type, and lifetime data.
|
||||
m_signature = "tbd";
|
||||
|
||||
// Get a StringBuffer to help us with the construction of the token
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
// Start building the message
|
||||
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
|
||||
sb.append("<" + ProtoDefs.authTokenElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.signatureElementName + ">" + m_signature + "</" + ProtoDefs.signatureElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.lifetimeElementName + ">" + m_lifetime + "</" + ProtoDefs.lifetimeElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.identTokenElementName + ">"
|
||||
+ "<" + ProtoDefs.typeElementName + ">" + m_identityTokenType + "</" + ProtoDefs.typeElementName + ">"
|
||||
+ m_identityToken + "</" + ProtoDefs.identTokenElementName + ">" + "\r\n");
|
||||
sb.append("</" + ProtoDefs.authTokenElementName + ">" + "\r\n");
|
||||
|
||||
// Save the token
|
||||
m_token = sb.toString();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// tbd
|
||||
System.err.println("AuthToken()- Exception: " + e.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Error: Missing authentication token config for " + targetService);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor given an authentication token string. The constructor
|
||||
* validates the token as part of its processing.
|
||||
*/
|
||||
public AuthToken(String token) throws Exception
|
||||
{
|
||||
// Decode the token string
|
||||
m_token = Base64Coder.decode(token);
|
||||
|
||||
// Instantiate string buffer for the identity token
|
||||
m_identityToken = new StringBuffer();
|
||||
|
||||
// Now parse the token into its elements
|
||||
try
|
||||
{
|
||||
// Parse the AuthToken
|
||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
||||
SAXHandler handler = new SAXHandler(this);
|
||||
xr.setContentHandler(handler);
|
||||
xr.setErrorHandler(handler);
|
||||
|
||||
ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes());
|
||||
InputSource source = new InputSource(inStream);
|
||||
xr.parse(source);
|
||||
|
||||
// Verify the signature
|
||||
// tbd
|
||||
|
||||
// Verify that the token has not expired
|
||||
// tbd
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
System.err.println("AuthToken()- Parse exception: " + e.toString());
|
||||
throw new Exception("Protocol error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containing the Base64 encode token.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return Base64Coder.encode(m_token);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the lifetime of the token.
|
||||
*/
|
||||
public String getLifetime()
|
||||
{
|
||||
// tbd - Convert to tokenLifetime and lifetimeShorter to ints, substractand then convert result to string
|
||||
return "60";
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the identity token.
|
||||
*/
|
||||
public String getIdentityToken()
|
||||
{
|
||||
return m_identityToken.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the identity token type.
|
||||
*/
|
||||
public String getIdentityTokenType()
|
||||
{
|
||||
return m_identityTokenType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
* AuthTokenConfig Class.
|
||||
*
|
||||
* This class obtains and maintains authentication token configuration.
|
||||
*
|
||||
*/
|
||||
public class AuthTokenConfig
|
||||
{
|
||||
// Well known authentication token configuration settings
|
||||
public final static String TokenLifetime = "TokenLifetime";
|
||||
public final static String LifetimeShorter = "LifetimeShorter";
|
||||
public final static String IdentityTokenType = "IdentityTokenType";
|
||||
|
||||
// Default configuration values
|
||||
private String m_defaultTokenLifetimeValue = "3600"; // Seconds
|
||||
private String m_defaultLifetimeShorterValue = "5"; // Seconds
|
||||
private String m_defaultIdentityTokenTypeValue = "CasaIdentityToken";
|
||||
|
||||
private Map m_tokenSettingsMap;
|
||||
|
||||
/*
|
||||
* Class for handling parsing events.
|
||||
*/
|
||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
||||
{
|
||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
||||
private final static int AWAITING_SETTING_ELEMENT_START = 1;
|
||||
private final static int AWAITING_SETTING_ELEMENT_DATA = 2;
|
||||
private final static int AWAITING_SETTING_ELEMENT_END = 3;
|
||||
private final static int DONE_PARSING = 4;
|
||||
|
||||
private final static String m_rootElementName = "settings";
|
||||
|
||||
private Map m_keyMap;
|
||||
private int m_state;
|
||||
private String m_currentKey;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SAXHandler(Map keyMap)
|
||||
{
|
||||
super();
|
||||
|
||||
// Initialize our members
|
||||
m_keyMap = keyMap;
|
||||
m_state = AWAITING_ROOT_ELEMENT_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* endDocument() implementation.
|
||||
*/
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
// Verify that we are not in an invalid state
|
||||
if (m_state != DONE_PARSING)
|
||||
{
|
||||
System.err.println("AuthTokenConfig SAXHandler.endDocument()- Invalid state" + m_state);
|
||||
throw new SAXException("Invalid state at endDocument");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* startElement() implementation.
|
||||
*/
|
||||
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
case AWAITING_ROOT_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (m_rootElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthTokenConfig SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SETTING_ELEMENT_START:
|
||||
// Keep track of the key name
|
||||
m_currentKey = qName;
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_DATA;
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("AuthTokenConfig SAXHandler.startElement()- Invalid state " + m_state);
|
||||
throw new SAXException("Invalid state at startElement");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endElement() immplementation.
|
||||
*/
|
||||
public void endElement (String uri, String name, String qName) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
case AWAITING_SETTING_ELEMENT_DATA:
|
||||
case AWAITING_SETTING_ELEMENT_END:
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_START;
|
||||
break;
|
||||
|
||||
case AWAITING_SETTING_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (m_rootElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = DONE_PARSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthTokenConfig SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("AuthTokenConfig SAXHandler.endElement()- Invalid state " + m_state);
|
||||
throw new SAXException("Invalid state at endElement");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* character() implementation.
|
||||
*/
|
||||
public void characters (char ch[], int start, int length) throws SAXException
|
||||
{
|
||||
// Consume the data if in the right state
|
||||
if (m_state == AWAITING_SETTING_ELEMENT_DATA)
|
||||
{
|
||||
// Consume the data and add the key to map
|
||||
m_keyMap.put(m_currentKey, new String(ch, start, length));
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor which sets default configuration values.
|
||||
*/
|
||||
public AuthTokenConfig() throws Exception
|
||||
{
|
||||
System.err.println("AuthTokenConfig()- Default");
|
||||
|
||||
// Create a map to keep track of the token settings
|
||||
m_tokenSettingsMap = new HashMap();
|
||||
|
||||
// Set the default settings in our map
|
||||
m_tokenSettingsMap.put(TokenLifetime, m_defaultTokenLifetimeValue);
|
||||
m_tokenSettingsMap.put(LifetimeShorter, m_defaultLifetimeShorterValue);
|
||||
m_tokenSettingsMap.put(IdentityTokenType, m_defaultIdentityTokenTypeValue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public AuthTokenConfig(String authTokenSettingsFileName) throws Exception
|
||||
{
|
||||
System.err.println("AuthTokenConfig()-");
|
||||
|
||||
// Create a map to keep track of the token settings
|
||||
m_tokenSettingsMap = new HashMap();
|
||||
|
||||
try
|
||||
{
|
||||
// Get an input stream to read from the token settings file
|
||||
File f = new File(authTokenSettingsFileName);
|
||||
FileInputStream inStream = new FileInputStream(f);
|
||||
|
||||
// Parse the file
|
||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
||||
SAXHandler handler = new SAXHandler(m_tokenSettingsMap);
|
||||
xr.setContentHandler(handler);
|
||||
xr.setErrorHandler(handler);
|
||||
|
||||
InputSource source = new InputSource(inStream);
|
||||
xr.parse(source);
|
||||
|
||||
inStream.close();
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
System.err.println("AuthTokenConfig()- " + authTokenSettingsFileName + " format error, exception: " + e.toString());
|
||||
throw new Exception("AuthTokenConfig()- authtoken.settings format error");
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("AuthTokenConfig()- SecurityException accessing " + authTokenSettingsFileName + " Exception=" + e.toString());
|
||||
throw new Exception("AuthTokenConfig()- Not able to access file");
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
System.err.println("AuthTokenConfig()- File " + authTokenSettingsFileName + " not found");
|
||||
throw new Exception("AuthTokenConfig()- File not found");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println("AuthTokenConfig()- IOException accessing " + authTokenSettingsFileName + " Exception=" + e.toString());
|
||||
throw new Exception("AuthTokenConfig()- Read error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the value associated with the specified setting.
|
||||
*/
|
||||
public String getSetting(String settingName) throws Exception
|
||||
{
|
||||
// Try to find the setting in our map
|
||||
String value = (String) m_tokenSettingsMap.get(settingName);
|
||||
if (value == null)
|
||||
{
|
||||
System.err.println("AuthTokenConfig.getSetting()- Did not find setting " + settingName);
|
||||
|
||||
// The setting is not in our map, check if it is one to
|
||||
// which we have defaults.
|
||||
if (settingName.equals(TokenLifetime) == true)
|
||||
{
|
||||
value = m_defaultTokenLifetimeValue;
|
||||
System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value);
|
||||
|
||||
// Add the key to the map so that it can be found quicker next time
|
||||
m_tokenSettingsMap.put(TokenLifetime, m_defaultTokenLifetimeValue);
|
||||
}
|
||||
else if (settingName.equals(LifetimeShorter) == true)
|
||||
{
|
||||
value = m_defaultLifetimeShorterValue;
|
||||
System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value);
|
||||
|
||||
// Add the key to the map so that it can be found quicker next time
|
||||
m_tokenSettingsMap.put(LifetimeShorter, m_defaultLifetimeShorterValue);
|
||||
}
|
||||
else if (settingName.equals(IdentityTokenType) == true)
|
||||
{
|
||||
value = m_defaultLifetimeShorterValue;
|
||||
System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value);
|
||||
|
||||
// Add the key to the map so that it can be found quicker next time
|
||||
m_tokenSettingsMap.put(IdentityTokenType, m_defaultIdentityTokenTypeValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("AuthTokenConfig.getSetting()- Found setting " + settingName);
|
||||
System.err.println("AuthTokenConfig.getSetting()- Setting value = " + value);
|
||||
|
||||
// Do some sanity checking
|
||||
// tbd - Make sure that the token lifetime values are greater than the LifetimeShorter
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
/**
|
||||
* Authenticate Class.
|
||||
*
|
||||
* This class processes authentication requests.
|
||||
*
|
||||
*/
|
||||
public class Authenticate implements RpcMethod
|
||||
{
|
||||
private static final String m_mechanismSettingsFileName = "mechanism.settings";
|
||||
|
||||
private Map m_authMechanismMap;
|
||||
|
||||
private SvcConfig m_svcConfig;
|
||||
private EnabledSvcsConfig m_enabledSvcsConfig;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public Authenticate() throws Exception
|
||||
{
|
||||
// Create a map to keep track of the authentication mechanisms
|
||||
m_authMechanismMap = new HashMap();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the Rpc method.
|
||||
*/
|
||||
public void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception
|
||||
{
|
||||
m_svcConfig = svcConfig;
|
||||
m_enabledSvcsConfig = enabledSvcsConfig;
|
||||
|
||||
// Now go through the configured authentication mechanisms, as we do so, instantiate
|
||||
// the mechanisms and place them in our map. Note that the mechanisms config folder
|
||||
// contains folders for each installed authentication mechanism. The name of these
|
||||
// folders usually match the name of the Authentication mechanisms.
|
||||
String svcConfigPath = svcConfig.getSetting(SvcConfig.ConfigFolderPath);
|
||||
File mechanismsConfigFolder = new File(svcConfigPath, "auth_mechanisms");
|
||||
try
|
||||
{
|
||||
String[] mechanismsConfigFolderObjs = mechanismsConfigFolder.list();
|
||||
if (mechanismsConfigFolderObjs != null)
|
||||
{
|
||||
for (int i = 0; i < mechanismsConfigFolderObjs.length; i++)
|
||||
{
|
||||
// Check if we are dealing with a file or a folder
|
||||
File mechanismFolder = new File(mechanismsConfigFolder, mechanismsConfigFolderObjs[i]);
|
||||
try
|
||||
{
|
||||
if (mechanismFolder.isDirectory() == true)
|
||||
{
|
||||
System.err.println("Authenticate.init()- Mechanism folder " + mechanismFolder + " is directory");
|
||||
|
||||
// Try to obtain the mechanism settings
|
||||
try
|
||||
{
|
||||
AuthMechConfig mechConfig = new AuthMechConfig(mechanismFolder + File.separator + m_mechanismSettingsFileName);
|
||||
|
||||
// Mechanism settings obtained, now instantiate it and place it in our map.
|
||||
//
|
||||
String mechClassName = mechConfig.getSetting(AuthMechConfig.ClassName);
|
||||
if (mechClassName != null)
|
||||
{
|
||||
// We now know the name of the class implementing the mechanism, now lets
|
||||
// get the relative path to the class file. Note that the path is relative
|
||||
// to the root folder of our application.
|
||||
String relativePath = mechConfig.getSetting(AuthMechConfig.RelativeClassPath);
|
||||
if (relativePath != null)
|
||||
{
|
||||
// Create a file object to the folder containing the class file. Note that we need to
|
||||
// ultimately instantiate objects from a class loaded by the same class loader that
|
||||
// loads the AuthMechanism class to avoid ClassCastExceptions.
|
||||
File mechClassPathFile = new File(svcConfig.getSetting(SvcConfig.AppRootPath) + relativePath);
|
||||
System.err.println("Authenticate.init()- Mechanism path = " + mechClassPathFile);
|
||||
try
|
||||
{
|
||||
URL methClassPathUrl = mechClassPathFile.toURL();
|
||||
URL[] urls = new URL[]{methClassPathUrl};
|
||||
|
||||
// Create a class loader for the folder
|
||||
ClassLoader customClassLoader = new URLClassLoader(urls);
|
||||
|
||||
// Load the mech class using our custom loader
|
||||
Class mechClass = customClassLoader.loadClass(mechClassName);
|
||||
FileOutputStream fos = new FileOutputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp");
|
||||
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
||||
oos.writeObject(mechClass);
|
||||
oos.close();
|
||||
fos.close();
|
||||
FileInputStream fis = new FileInputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp");
|
||||
ObjectInputStream ois = new ObjectInputStream(fis);
|
||||
mechClass = (Class) ois.readObject();
|
||||
ois.close();
|
||||
fis.close();
|
||||
|
||||
// Now reload the class using the class loader for our AuthMechanism class
|
||||
AuthMechanism mechanism = (AuthMechanism) mechClass.newInstance();
|
||||
mechanism.init(svcConfig, mechConfig);
|
||||
m_authMechanismMap.put(mechanism.getId(), mechanism);
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- MalformedURLException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- ClassNotFoundException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- InstantiationException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- IllegalAccessException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// A relative path was not configured, check if instead a full path was configured.
|
||||
String classPath = mechConfig.getSetting(AuthMechConfig.ClassPath);
|
||||
if (classPath != null)
|
||||
{
|
||||
// Create a file object to the folder containing the class file. Note that we need to
|
||||
// ultimately instantiate objects from a class loaded by the same class loader that
|
||||
// loads the AuthMechanism class to avoid ClassCastExceptions.
|
||||
File mechClassPathFile = new File(classPath);
|
||||
System.err.println("Authenticate.init()- Mechanism path = " + mechClassPathFile);
|
||||
try
|
||||
{
|
||||
URL methClassPathUrl = mechClassPathFile.toURL();
|
||||
URL[] urls = new URL[]{methClassPathUrl};
|
||||
|
||||
// Create a class loader for the folder
|
||||
ClassLoader customClassLoader = new URLClassLoader(urls);
|
||||
|
||||
// Load the mech class using our custom loader
|
||||
Class mechClass = customClassLoader.loadClass(mechClassName);
|
||||
FileOutputStream fos = new FileOutputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp");
|
||||
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
||||
oos.writeObject(mechClass);
|
||||
oos.close();
|
||||
fos.close();
|
||||
FileInputStream fis = new FileInputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp");
|
||||
ObjectInputStream ois = new ObjectInputStream(fis);
|
||||
mechClass = (Class) ois.readObject();
|
||||
ois.close();
|
||||
fis.close();
|
||||
|
||||
// Now reload the class using the class loader for our AuthMechanism class
|
||||
AuthMechanism mechanism = (AuthMechanism) mechClass.newInstance();
|
||||
mechanism.init(svcConfig, mechConfig);
|
||||
m_authMechanismMap.put(mechanism.getId(), mechanism);
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- MalformedURLException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- ClassNotFoundException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- InstantiationException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- IllegalAccessException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Authenticate.init()- No configuration to find class path to load " + mechanismFolder + File.separator + m_mechanismSettingsFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Authenticate.init()- No configured mechanism class name for " + mechanismFolder + File.separator + m_mechanismSettingsFileName);
|
||||
}
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- SecurityException accessing " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- No authentication policy file for " + mechanismFolder);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- IOException reading " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- Exception instantiating mechConfig or mechanism " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- SecurityException accessing " + mechanismFolder + " Exception=" + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Authenticate.init()- Unable to obtain mechanisms folder " + mechanismsConfigFolder + " objects");
|
||||
}
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("Authenticate.init()- SecurityException accessing " + mechanismsConfigFolder + " Exception=" + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process Rpc.
|
||||
*/
|
||||
public void invoke(InputStream inStream, PrintWriter out) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
System.err.println("Authenticate.invoke()");
|
||||
|
||||
// Parse the AuthReqMsg sent from the client
|
||||
AuthReqMsg authReqMsg = new AuthReqMsg(inStream);
|
||||
|
||||
// Get the necessary authentication mechanism
|
||||
AuthMechanism authMechanism = (AuthMechanism) m_authMechanismMap.get(authReqMsg.getMechanismId());
|
||||
if (authMechanism != null)
|
||||
{
|
||||
// Invoke the mechanism to authenticate the entity
|
||||
String identId = authMechanism.invoke(authReqMsg);
|
||||
|
||||
// Create response based on the identity resolution results
|
||||
if (identId != null && identId.length() != 0)
|
||||
{
|
||||
System.err.println("Authenticate.invoke()- identId resolved, " + identId);
|
||||
|
||||
// An identity was resolved, get a SessionToken for it.
|
||||
SessionToken sessionToken = new SessionToken(identId,
|
||||
authReqMsg.getRealm(),
|
||||
m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime));
|
||||
|
||||
// Write out the response
|
||||
AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpOkStatusMsg,
|
||||
ProtoDefs.httpOkStatusCode,
|
||||
sessionToken.toString(),
|
||||
m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime));
|
||||
// tbd - Convert to ints, perform calculation, and then convert result to string
|
||||
//m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime)
|
||||
//- m_svcConfig.getSetting(SvcConfig.LifetimeShorter));
|
||||
out.println(authRespMsg.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Authenticate.invoke()- identId not resolved");
|
||||
|
||||
// Write out the response
|
||||
AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpUnauthorizedStatusMsg,
|
||||
ProtoDefs.httpUnauthorizedStatusCode);
|
||||
out.println(authRespMsg.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Authenticate.invoke()- Unsupported mechanism " + authReqMsg.getMechanismId());
|
||||
|
||||
// Write out the response
|
||||
AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpNotFoundStatusMsg,
|
||||
ProtoDefs.httpNotFoundStatusCode);
|
||||
out.println(authRespMsg.toString());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Authenticate.invoke()- Exception: " + e.toString());
|
||||
|
||||
// Write out the response
|
||||
try
|
||||
{
|
||||
AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpServerErrorStatusMsg,
|
||||
ProtoDefs.httpServerErrorStatusCode);
|
||||
out.println(authRespMsg.toString());
|
||||
}
|
||||
catch (Exception e2)
|
||||
{
|
||||
System.err.println("Authenticate.invoke()- Exception trying to construct response msg: " + e2.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the method id.
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return "Authenticate";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* A Base64 Encoder/Decoder.
|
||||
*
|
||||
* This class is used to encode and decode data in Base64 format
|
||||
* as described in RFC 1521.
|
||||
*
|
||||
* <p>
|
||||
* Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland.<br>
|
||||
* License: This is "Open Source" software and released under the <a href="http://www.gnu.org/licenses/lgpl.html" target="_top">GNU/LGPL</a> license.
|
||||
* It is provided "as is" without warranty of any kind. Please contact the author for other licensing arrangements.<br>
|
||||
* Home page: <a href="http://www.source-code.biz" target="_top">www.source-code.biz</a><br>
|
||||
*
|
||||
* <p>
|
||||
* Version history:<br>
|
||||
* 2003-07-22 Christian d'Heureuse (chdh): Module created.<br>
|
||||
* 2005-08-11 chdh: Lincense changed from GPL to LGPL.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
public class Base64Coder {
|
||||
|
||||
// Mapping table from 6-bit nibbles to Base64 characters.
|
||||
private static char[] map1 = new char[64];
|
||||
static {
|
||||
int i=0;
|
||||
for (char c='A'; c<='Z'; c++) map1[i++] = c;
|
||||
for (char c='a'; c<='z'; c++) map1[i++] = c;
|
||||
for (char c='0'; c<='9'; c++) map1[i++] = c;
|
||||
map1[i++] = '+'; map1[i++] = '/'; }
|
||||
|
||||
// Mapping table from Base64 characters to 6-bit nibbles.
|
||||
private static byte[] map2 = new byte[128];
|
||||
static {
|
||||
for (int i=0; i<map2.length; i++) map2[i] = -1;
|
||||
for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; }
|
||||
|
||||
/**
|
||||
* Encodes a string into Base64 format.
|
||||
* No blanks or line breaks are inserted.
|
||||
* @param s a String to be encoded.
|
||||
* @return A String with the Base64 encoded data.
|
||||
*/
|
||||
public static String encode (String s) {
|
||||
return new String(encode(s.getBytes())); }
|
||||
|
||||
/**
|
||||
* Encodes a byte array into Base64 format.
|
||||
* No blanks or line breaks are inserted.
|
||||
* @param in an array containing the data bytes to be encoded.
|
||||
* @return A character array with the Base64 encoded data.
|
||||
*/
|
||||
public static char[] encode (byte[] in) {
|
||||
int iLen = in.length;
|
||||
int oDataLen = (iLen*4+2)/3; // output length without padding
|
||||
int oLen = ((iLen+2)/3)*4; // output length including padding
|
||||
char[] out = new char[oLen];
|
||||
int ip = 0;
|
||||
int op = 0;
|
||||
while (ip < iLen) {
|
||||
int i0 = in[ip++] & 0xff;
|
||||
int i1 = ip < iLen ? in[ip++] & 0xff : 0;
|
||||
int i2 = ip < iLen ? in[ip++] & 0xff : 0;
|
||||
int o0 = i0 >>> 2;
|
||||
int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
|
||||
int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
|
||||
int o3 = i2 & 0x3F;
|
||||
out[op++] = map1[o0];
|
||||
out[op++] = map1[o1];
|
||||
out[op] = op < oDataLen ? map1[o2] : '='; op++;
|
||||
out[op] = op < oDataLen ? map1[o3] : '='; op++; }
|
||||
return out; }
|
||||
|
||||
/**
|
||||
* Decodes a Base64 string.
|
||||
* @param s a Base64 String to be decoded.
|
||||
* @return A String containing the decoded data.
|
||||
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
|
||||
*/
|
||||
public static String decode (String s) {
|
||||
return new String(decode(s.toCharArray())); }
|
||||
|
||||
/**
|
||||
* Decodes Base64 data.
|
||||
* No blanks or line breaks are allowed within the Base64 encoded data.
|
||||
* @param in a character array containing the Base64 encoded data.
|
||||
* @return An array containing the decoded data bytes.
|
||||
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
|
||||
*/
|
||||
public static byte[] decode (char[] in) {
|
||||
int iLen = in.length;
|
||||
if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4.");
|
||||
while (iLen > 0 && in[iLen-1] == '=') iLen--;
|
||||
int oLen = (iLen*3) / 4;
|
||||
byte[] out = new byte[oLen];
|
||||
int ip = 0;
|
||||
int op = 0;
|
||||
while (ip < iLen) {
|
||||
int i0 = in[ip++];
|
||||
int i1 = in[ip++];
|
||||
int i2 = ip < iLen ? in[ip++] : 'A';
|
||||
int i3 = ip < iLen ? in[ip++] : 'A';
|
||||
if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
|
||||
throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");
|
||||
int b0 = map2[i0];
|
||||
int b1 = map2[i1];
|
||||
int b2 = map2[i2];
|
||||
int b3 = map2[i3];
|
||||
if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
|
||||
throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");
|
||||
int o0 = ( b0 <<2) | (b1>>>4);
|
||||
int o1 = ((b1 & 0xf)<<4) | (b2>>>2);
|
||||
int o2 = ((b2 & 3)<<6) | b3;
|
||||
out[op++] = (byte)o0;
|
||||
if (op<oLen) out[op++] = (byte)o1;
|
||||
if (op<oLen) out[op++] = (byte)o2; }
|
||||
return out; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,775 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
import org.bandit.ia.IAContext;
|
||||
|
||||
/*
|
||||
* CasaIdentityToken Class.
|
||||
*
|
||||
* This class constructs Casa Identity tokens.
|
||||
*
|
||||
* A Casa Identity Token is a simple XML Document
|
||||
* with information about an identity in the form
|
||||
* of:
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <casa_ident_tok>
|
||||
* <id>identity id</id>
|
||||
* <source_name>identity data source name</source_name>
|
||||
* <source_url>identity data source url</source_url>
|
||||
* <target_service>target service name</target_service>
|
||||
* <target_host>target host name</target_host>
|
||||
* <attributes>
|
||||
* <attribute name>attribute value</attribute name>
|
||||
* <attribute2 name>attribute2 value</attribute name>
|
||||
* ...
|
||||
* </attributes>
|
||||
* </casa_ident_tok>
|
||||
*
|
||||
*
|
||||
* attribute/values pairs. The attribute names
|
||||
* being the XML elements of the documents.
|
||||
*
|
||||
*/
|
||||
public class CasaIdentityToken implements IdentityToken
|
||||
{
|
||||
/*
|
||||
* XML Element Name Constants for the documents exchanged between the
|
||||
* Casa Client and the Casa Server.
|
||||
*/
|
||||
private final static String casaIdentTokElementName = "casa_ident_tok";
|
||||
private final static String idElementName = "id";
|
||||
private final static String sourceNameElementName = "source_name";
|
||||
private final static String sourceUrlElementName = "source_url";
|
||||
private final static String targetServiceElementName = "target_service";
|
||||
private final static String targetHostElementName = "target_host";
|
||||
private final static String attributesElementName = "attributes";
|
||||
|
||||
private IdenTokenConfig m_idenTokenConfig;
|
||||
|
||||
private String m_identityId = null;
|
||||
private String m_sourceName = null;
|
||||
private String m_sourceUrl = null;
|
||||
private String m_service = null;
|
||||
private String m_host = null;
|
||||
private String m_token = null;
|
||||
private javax.naming.directory.Attributes m_attributes = null;
|
||||
|
||||
/*
|
||||
* Class for handling Authentication Request parsing events.
|
||||
*/
|
||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
||||
{
|
||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
||||
private final static int AWAITING_ROOT_ELEMENT_END = 1;
|
||||
private final static int AWAITING_ID_ELEMENT_START = 2;
|
||||
private final static int AWAITING_ID_ELEMENT_END = 3;
|
||||
private final static int AWAITING_ID_DATA = 4;
|
||||
private final static int AWAITING_SOURCE_NAME_ELEMENT_START = 5;
|
||||
private final static int AWAITING_SOURCE_NAME_ELEMENT_END = 6;
|
||||
private final static int AWAITING_SOURCE_NAME_DATA = 7;
|
||||
private final static int AWAITING_SOURCE_URL_ELEMENT_START = 8;
|
||||
private final static int AWAITING_SOURCE_URL_ELEMENT_END = 9;
|
||||
private final static int AWAITING_SOURCE_URL_DATA = 10;
|
||||
private final static int AWAITING_TARGET_SERVICE_ELEMENT_START = 11;
|
||||
private final static int AWAITING_TARGET_SERVICE_ELEMENT_END = 12;
|
||||
private final static int AWAITING_TARGET_SERVICE_DATA = 13;
|
||||
private final static int AWAITING_TARGET_HOST_ELEMENT_START = 14;
|
||||
private final static int AWAITING_TARGET_HOST_ELEMENT_END = 15;
|
||||
private final static int AWAITING_TARGET_HOST_DATA = 16;
|
||||
private final static int AWAITING_ATTRIBUTES_ELEMENT_START = 17;
|
||||
private final static int AWAITING_ATTRIBUTE_START = 18;
|
||||
private final static int AWAITING_ATTRIBUTE_END = 19;
|
||||
private final static int AWAITING_ATTRIBUTE_DATA = 20;
|
||||
private final static int AWAITING_BINARY_ATTRIBUTE_DATA = 21;
|
||||
private final static int DONE_PARSING = 22;
|
||||
|
||||
private CasaIdentityToken m_casaIdentToken;
|
||||
private int m_state;
|
||||
private String m_currAttribute;
|
||||
private boolean m_encryptedAttrs;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SAXHandler (CasaIdentityToken casaIdentityToken)
|
||||
{
|
||||
super();
|
||||
|
||||
// Initialize our members
|
||||
m_casaIdentToken = casaIdentityToken;
|
||||
m_state = AWAITING_ROOT_ELEMENT_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* endDocument() implementation.
|
||||
*/
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
// Verify that we obtained all of the required elements
|
||||
if (m_state != DONE_PARSING)
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.endDocument()- Missing element");
|
||||
throw new SAXException("Missing element");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* startElement() implementation.
|
||||
*/
|
||||
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_ROOT_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (casaIdentTokElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ID_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_ID_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (idElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ID_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SOURCE_NAME_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (sourceNameElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SOURCE_NAME_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AWAITING_SOURCE_URL_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (sourceUrlElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SOURCE_URL_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_TARGET_SERVICE_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (targetServiceElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_TARGET_SERVICE_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_TARGET_HOST_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (targetHostElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_TARGET_HOST_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_ATTRIBUTES_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (attributesElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ATTRIBUTE_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_ATTRIBUTE_START:
|
||||
// Save the element name as the current attribute
|
||||
m_currAttribute = qName;
|
||||
|
||||
// Advance to the next state based on the attribute type
|
||||
String attrType = atts.getValue("type");
|
||||
if (attrType != null && attrType.equals("binary"))
|
||||
{
|
||||
// We are dealing with a binary attribute. We are going to
|
||||
// assume that binary attributes are always base64 encoded.
|
||||
m_state = AWAITING_BINARY_ATTRIBUTE_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume we are dealing with an attribute of type string
|
||||
m_state = AWAITING_ATTRIBUTE_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("CasaIdentityToken SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endElement() immplementation.
|
||||
*/
|
||||
public void endElement (String uri, String name, String qName) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_ROOT_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (casaIdentTokElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = DONE_PARSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_ID_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (idElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SOURCE_NAME_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SOURCE_NAME_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (sourceNameElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SOURCE_URL_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SOURCE_URL_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (sourceUrlElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_TARGET_SERVICE_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_TARGET_SERVICE_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (targetServiceElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_TARGET_HOST_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_TARGET_HOST_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (targetHostElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ATTRIBUTES_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_ATTRIBUTE_END:
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ATTRIBUTE_START;
|
||||
break;
|
||||
|
||||
case AWAITING_ATTRIBUTE_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (attributesElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ROOT_ELEMENT_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("CasaIdentityToken SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* character() implementation.
|
||||
*/
|
||||
public void characters (char ch[], int start, int length) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_ID_DATA:
|
||||
// Consume the data
|
||||
m_casaIdentToken.m_identityId = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ID_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_SOURCE_NAME_DATA:
|
||||
// Consume the data
|
||||
m_casaIdentToken.m_sourceName = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SOURCE_NAME_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_SOURCE_URL_DATA:
|
||||
// Consume the data
|
||||
m_casaIdentToken.m_sourceUrl = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SOURCE_URL_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_TARGET_SERVICE_DATA:
|
||||
// Consume the data
|
||||
m_casaIdentToken.m_service = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_TARGET_SERVICE_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_TARGET_HOST_DATA:
|
||||
// Consume the data
|
||||
m_casaIdentToken.m_host = new String(ch, start, length);
|
||||
|
||||
// At this point we now have the target service and host names,
|
||||
// check if our configuration says that the attributes have been
|
||||
// encrypted.
|
||||
// tbd - Need to come up with a solution for obtaining configuration
|
||||
// information when instanstiated using a stream. May be the token should
|
||||
// carry an indication that the attributes are encrypted.
|
||||
m_encryptedAttrs = false;
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_TARGET_HOST_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_ATTRIBUTE_DATA:
|
||||
// Consume the data
|
||||
//
|
||||
// Decrypt the attribute data if necessary
|
||||
if (m_encryptedAttrs)
|
||||
{
|
||||
// tbd - Decrypt the attribute key and value with the private key of the service
|
||||
// using the configured mechanism.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_casaIdentToken.m_attributes.put(m_currAttribute, new String(ch, start, length));
|
||||
}
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ATTRIBUTE_END;
|
||||
break;
|
||||
|
||||
case AWAITING_BINARY_ATTRIBUTE_DATA:
|
||||
// Consume the data
|
||||
//
|
||||
// Decrypt the attribute data if necessary
|
||||
if (m_encryptedAttrs)
|
||||
{
|
||||
// tbd - Decrypt the attribute key and value with the private key of the service
|
||||
// using the configured mechanism.
|
||||
}
|
||||
else
|
||||
{
|
||||
// The data is base64 encoded
|
||||
char[] encodedChars = new char[length];
|
||||
System.arraycopy(ch, start, encodedChars, 0, length);
|
||||
m_casaIdentToken.m_attributes.put(m_currAttribute, Base64Coder.decode(encodedChars));
|
||||
}
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ATTRIBUTE_END;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public CasaIdentityToken (IdenTokenConfig idenTokenConfig)
|
||||
{
|
||||
// Initialize our members
|
||||
m_token = null;
|
||||
m_attributes = new javax.naming.directory.BasicAttributes();
|
||||
m_idenTokenConfig = idenTokenConfig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public CasaIdentityToken ()
|
||||
{
|
||||
// Initialize our members
|
||||
m_token = null;
|
||||
m_attributes = new javax.naming.directory.BasicAttributes();
|
||||
m_idenTokenConfig = null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize with parameters.
|
||||
*/
|
||||
public void initialize (String identityId,
|
||||
String sourceName,
|
||||
String targetService,
|
||||
String targetHost,
|
||||
SvcConfig svcConfig) throws Exception
|
||||
{
|
||||
// Save input parameters
|
||||
m_identityId = identityId;
|
||||
m_sourceName = sourceName;
|
||||
m_sourceUrl = "ldap://myldaphost.novell.com:389"; // tbd - Obtain from Identity Abstraction layer
|
||||
m_service = targetService;
|
||||
m_host = targetHost;
|
||||
|
||||
try
|
||||
{
|
||||
// Open a directory context and use it to read the identity attributes.
|
||||
Hashtable env = new Hashtable();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
|
||||
env.put(IAContext.IA_REALM_CONFIG_LOCATION, svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
|
||||
env.put("java.naming.ldap.attributes.binary", "guid");
|
||||
env.put(IAContext.IA_REALM_SELECTOR, sourceName);
|
||||
|
||||
DirContext ctx = new InitialDirContext(env);
|
||||
|
||||
// Setup a string buffer for building the IdentityToken, notice for now
|
||||
// we are not going to wrap the identity token.
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
|
||||
sb.append("<" + casaIdentTokElementName + ">" + "\r\n");
|
||||
sb.append("<" + idElementName + ">" + identityId + "</" + idElementName + ">\r\n");
|
||||
sb.append("<" + sourceNameElementName + ">" + sourceName + "</" + sourceNameElementName + ">\r\n");
|
||||
sb.append("<" + sourceUrlElementName + ">" + m_sourceUrl + "</" + sourceUrlElementName + ">\r\n");
|
||||
sb.append("<" + targetServiceElementName + ">" + m_service + "</" + targetServiceElementName + ">\r\n");
|
||||
sb.append("<" + targetHostElementName + ">" + m_host + "</" + targetHostElementName + ">\r\n");
|
||||
sb.append("<" + attributesElementName + ">" + "\r\n");
|
||||
|
||||
// Get the necessary attributes of the specified services in the identity token
|
||||
String[] attributesNeeded = m_idenTokenConfig.getAttributes();
|
||||
boolean encryptAttributes = "true".equals(m_idenTokenConfig.getSetting(IdenTokenConfig.EncryptAttributes));
|
||||
Attributes attrs = ctx.getAttributes(identityId, attributesNeeded);
|
||||
|
||||
// Now append the attributes to the token
|
||||
for (NamingEnumeration ae = attrs.getAll(); ae.hasMore();)
|
||||
{
|
||||
javax.naming.directory.Attribute attr = (javax.naming.directory.Attribute) ae.next();
|
||||
|
||||
NamingEnumeration enumeration = attr.getAll();
|
||||
while (enumeration.hasMore())
|
||||
{
|
||||
Object attrValue = enumeration.next();
|
||||
m_attributes.put(attr.getID(), attrValue);
|
||||
System.err.println("CasaIdentityToken.initialize()- Including attribute " + attr.getID());
|
||||
|
||||
// Encrypt the attribute if necessary
|
||||
if (encryptAttributes == true)
|
||||
{
|
||||
// tbd - Encrypt the attributes using the services public key, let the mechanism
|
||||
// be configurable. The service's certificate should be Base64 encoded as a setting
|
||||
// of the identoken.settings file.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Proceed based on the attribute value type
|
||||
if (attrValue instanceof byte[])
|
||||
{
|
||||
// The attribute value is of type byte[], we need to encode it.
|
||||
sb.append("<" + attr.getID() + " type=\"binary\" encoding=\"base64\">" + new String(Base64Coder.encode((byte[]) attrValue)) + "</" + attr.getID() + ">" + "\r\n");
|
||||
System.err.println("Attribute " + attr.getID() + "included as " + new String(Base64Coder.encode((byte[]) attrValue)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume the attribute value is of type String
|
||||
sb.append("<" + attr.getID() + ">" + (String) attrValue + "</" + attr.getID() + ">" + "\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.append("</" + attributesElementName + ">" + "\r\n");
|
||||
sb.append("</" + casaIdentTokElementName + ">" + "\r\n");
|
||||
|
||||
m_token = sb.toString();
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
// tbd - Log the event???
|
||||
System.err.println("CasaIdentityToken.initialize()- Exception: " + e.getExplanation());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// tbd
|
||||
System.err.println("CasaIdentityToken.initialize()- Exception: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the token object with an ecoded token string.
|
||||
*/
|
||||
public void initialize (String encodedToken) throws Exception
|
||||
{
|
||||
// Save copy of the token
|
||||
m_token = Base64Coder.decode(encodedToken);
|
||||
|
||||
// Now parse the token into its elements
|
||||
try
|
||||
{
|
||||
// Parse the AuthReqMsg
|
||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
||||
SAXHandler handler = new SAXHandler(this);
|
||||
xr.setContentHandler(handler);
|
||||
xr.setErrorHandler(handler);
|
||||
|
||||
|
||||
ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes());
|
||||
InputSource source = new InputSource(inStream);
|
||||
xr.parse(source);
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
// tbd - Log this.
|
||||
System.err.println("CasaIdentityToken()- Parse exception: " + e.toString());
|
||||
throw new Exception("Token error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns encoded token string.
|
||||
*
|
||||
* IMPORTANT: The token string can not contain the substring "]]>"
|
||||
* within it.
|
||||
*/
|
||||
public String getEncodedToken () throws Exception
|
||||
{
|
||||
if (m_token != null)
|
||||
{
|
||||
return Base64Coder.encode(m_token);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken.toString()- Not initialized");
|
||||
throw new Exception("Not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containing our type of identity token provider.
|
||||
*/
|
||||
public String getProviderType () throws Exception
|
||||
{
|
||||
// tbd - Change to a GUID
|
||||
return "CasaIdentityToken";
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containing the identity id.
|
||||
*/
|
||||
public String getIdentityId () throws Exception
|
||||
{
|
||||
if (m_identityId != null)
|
||||
return m_identityId;
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken.getIdentityId()- Not initialized");
|
||||
throw new Exception("Not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containing the name associated with the
|
||||
* identity source.
|
||||
*/
|
||||
public String getSourceName () throws Exception
|
||||
{
|
||||
if (m_sourceName != null)
|
||||
return m_sourceName;
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken.getSourceName()- Not initialized");
|
||||
throw new Exception("Not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containing the url associated with the
|
||||
* identity source.
|
||||
*/
|
||||
public String getSourceUrl () throws Exception
|
||||
{
|
||||
if (m_sourceUrl != null)
|
||||
return m_sourceUrl;
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken.getSourceUrl()- Not initialized");
|
||||
throw new Exception("Not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containing the name of the targeted service.
|
||||
*/
|
||||
public String getTargetService () throws Exception
|
||||
{
|
||||
if (m_service != null)
|
||||
return m_service;
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken.getTargetService()- Not initialized");
|
||||
throw new Exception("Not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containig the name of the host where the
|
||||
* targeted service resides.
|
||||
*/
|
||||
public String getTargetHost () throws Exception
|
||||
{
|
||||
if (m_host != null)
|
||||
return m_host;
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken.getTargetHost()- Not initialized");
|
||||
throw new Exception("Not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the attributes of the identity.
|
||||
*/
|
||||
public javax.naming.directory.Attributes getAttributes () throws Exception
|
||||
{
|
||||
if (m_attributes != null)
|
||||
return m_attributes;
|
||||
else
|
||||
{
|
||||
System.err.println("CasaIdentityToken.getIdentityAttributes()- Not initialized");
|
||||
throw new Exception("Not initialized");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,388 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* EnabledSvcsConfig Class.
|
||||
*
|
||||
* This class obtains and maintains configuration and policy information about
|
||||
* the services enabled to use Authentication Tokens.
|
||||
*
|
||||
*/
|
||||
public class EnabledSvcsConfig
|
||||
{
|
||||
private static final String m_authPolicyFileName = "auth.policy";
|
||||
private static final String m_authTokenSettingsFileName = "authtoken.settings";
|
||||
private static final String m_idenTokenSettingsFileName = "identoken.settings";
|
||||
|
||||
private Map m_hostsMap;
|
||||
|
||||
/**
|
||||
* SvcConfigEntry Class.
|
||||
*
|
||||
* This class is used to maintain the configuration and policy associated with an
|
||||
* enabled service.
|
||||
*
|
||||
*/
|
||||
private class SvcConfigEntry
|
||||
{
|
||||
protected byte[] m_authPolicyFileData;
|
||||
protected AuthTokenConfig m_authTokenConfig;
|
||||
protected IdenTokenConfig m_idenTokenConfig;
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public SvcConfigEntry(byte[] authPolicyFileData,
|
||||
AuthTokenConfig authTokenConfig,
|
||||
IdenTokenConfig idenTokenConfig)
|
||||
{
|
||||
m_authPolicyFileData = authPolicyFileData;
|
||||
m_authTokenConfig = authTokenConfig;
|
||||
m_idenTokenConfig = idenTokenConfig;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public EnabledSvcsConfig(String svcConfigPath) throws Exception
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()-");
|
||||
System.err.println("EnabledSvcsConfig()- SvcConfigPath = " + svcConfigPath);
|
||||
|
||||
// Initialize the default auth policy, authtoken, and identtoken configs.
|
||||
byte[] defaultAuthPolicyData = null;
|
||||
AuthTokenConfig defaultAuthTokenConfig = null;
|
||||
IdenTokenConfig defaultIdenTokenConfig = null;
|
||||
|
||||
// Create a map to keep track of the enabled services and their configuration
|
||||
// for each configured host.
|
||||
m_hostsMap = new HashMap();
|
||||
|
||||
// Get access to the configuration folder for the service
|
||||
File configFolder = new File(svcConfigPath);
|
||||
try
|
||||
{
|
||||
// Try to obtain the default authentication policy
|
||||
try
|
||||
{
|
||||
File f = new File(configFolder, m_authPolicyFileName);
|
||||
defaultAuthPolicyData = new byte[(int) f.length()];
|
||||
FileInputStream inStream = new FileInputStream(f);
|
||||
int bytesRead = inStream.read(defaultAuthPolicyData);
|
||||
inStream.close();
|
||||
if (bytesRead != defaultAuthPolicyData.length)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- Error reading default policy file");
|
||||
}
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- SecurityException accessing " + configFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString());
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- File " + configFolder + File.separator + m_authPolicyFileName + " not found");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- IOException reading " + configFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString());
|
||||
}
|
||||
|
||||
// Try to obtain the default authentication token settings
|
||||
try
|
||||
{
|
||||
defaultAuthTokenConfig = new AuthTokenConfig(configFolder + File.separator + m_authTokenSettingsFileName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Not able to create authentication token configuration using the default
|
||||
// file. Create one using default parameters.
|
||||
defaultAuthTokenConfig = new AuthTokenConfig();
|
||||
}
|
||||
|
||||
// Try to obtain the default identity token settings
|
||||
try
|
||||
{
|
||||
defaultIdenTokenConfig = new IdenTokenConfig(configFolder + File.separator + m_idenTokenSettingsFileName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Not able to create identity token configuration using the default
|
||||
// file. Create one using default parameters.
|
||||
defaultIdenTokenConfig = new IdenTokenConfig();
|
||||
}
|
||||
|
||||
// Now go through the configured hosts. Note that the services config folder
|
||||
// contains folders for each host for which there are enabled services. The folders
|
||||
// in the services config folder must match the DNS name of the hosts where
|
||||
// the enabled services reside.
|
||||
File servicesConfigFolder = new File(svcConfigPath, "enabled_services");
|
||||
try
|
||||
{
|
||||
String[] servicesConfigFolderObjs = servicesConfigFolder.list();
|
||||
if (servicesConfigFolderObjs != null)
|
||||
{
|
||||
for (int i = 0; i < servicesConfigFolderObjs.length; i++)
|
||||
{
|
||||
// Check if we are dealing with a file or a folder
|
||||
File hostFolder = new File(servicesConfigFolder, servicesConfigFolderObjs[i]);
|
||||
try
|
||||
{
|
||||
if (hostFolder.isDirectory() == true)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- Host folder " + hostFolder + " is directory");
|
||||
|
||||
// Now go through the services configured for this host
|
||||
String[] hostFolderObjs = hostFolder.list();
|
||||
if (hostFolderObjs != null)
|
||||
{
|
||||
// Create a Map object to hold the service configurations for this host
|
||||
Map enabledSvcsConfigMap = new HashMap();
|
||||
|
||||
for (int ii = 0; ii < hostFolderObjs.length; ii++)
|
||||
{
|
||||
// Check if we are dealing with a file or a folder
|
||||
File serviceFolder = new File(hostFolder, hostFolderObjs[ii]);
|
||||
System.err.println("EnabledSvcsConfig()- Service folder " + serviceFolder);
|
||||
try
|
||||
{
|
||||
if (serviceFolder.isDirectory() == true)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- Service folder " + serviceFolder + " is directory");
|
||||
|
||||
// We are dealing with a folder, remember that the folder name matches the name
|
||||
// of the enabled service. Check and see if there are authentication policy and
|
||||
// authtoken and identoken setting files configured for it.
|
||||
byte[] authPolicyData = null;
|
||||
AuthTokenConfig authTokenConfig = null;
|
||||
IdenTokenConfig idenTokenConfig = null;
|
||||
|
||||
try
|
||||
{
|
||||
File policyFile = new File(serviceFolder, m_authPolicyFileName);
|
||||
authPolicyData = new byte[(int) policyFile.length()];
|
||||
FileInputStream inStream = new FileInputStream(policyFile);
|
||||
int bytesRead = inStream.read(authPolicyData);
|
||||
inStream.close();
|
||||
if (bytesRead != authPolicyData.length)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- Error reading policy file for " + servicesConfigFolderObjs[i] + " " + hostFolderObjs[ii]);
|
||||
}
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- SecurityException accessing " + serviceFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString());
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- No authentication policy file for " + serviceFolder);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- IOException reading " + serviceFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
authTokenConfig = new AuthTokenConfig(serviceFolder + File.separator + m_authTokenSettingsFileName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- Exception accessing " + serviceFolder + File.separator + m_authTokenSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
idenTokenConfig = new IdenTokenConfig(serviceFolder + File.separator + m_idenTokenSettingsFileName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- Exception accessing " + serviceFolder + File.separator + m_idenTokenSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
|
||||
// Make sure that we have a policy file
|
||||
if ((authPolicyData != null && authPolicyData.length != 0)
|
||||
|| (defaultAuthPolicyData != null && defaultAuthPolicyData.length != 0))
|
||||
{
|
||||
// Instantiate SvcConfigEntry for this service and place it in our map
|
||||
SvcConfigEntry svcConfigEntry = new SvcConfigEntry((authPolicyData != null && authPolicyData.length != 0) ? authPolicyData : defaultAuthPolicyData,
|
||||
(authTokenConfig != null) ? authTokenConfig : defaultAuthTokenConfig,
|
||||
(idenTokenConfig != null) ? idenTokenConfig : defaultIdenTokenConfig);
|
||||
|
||||
// Add this entry to our map
|
||||
System.err.println("EnabledSvcsConfig()- Adding entry in map for " + servicesConfigFolderObjs[i] + " " + hostFolderObjs[ii]);
|
||||
enabledSvcsConfigMap.put(hostFolderObjs[ii], svcConfigEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- Unable to enable " + servicesConfigFolderObjs[i] + " " + hostFolderObjs[ii] + " due to no configured authentication policy");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- SecurityException accessing " + serviceFolder + " Exception=" + e.toString());
|
||||
}
|
||||
|
||||
// Add this hosts enabled services configuration map to the hosts map
|
||||
m_hostsMap.put(servicesConfigFolderObjs[i], enabledSvcsConfigMap);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- No services configured for " + hostFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- SecurityException accessing " + hostFolder + " Exception=" + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- Unable to obtain services folder " + servicesConfigFolder + " objects");
|
||||
}
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- SecurityException accessing " + servicesConfigFolder + " Exception=" + e.toString());
|
||||
}
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("EnabledSvcsConfig()- SecurityException accessing " + configFolder + " Exception=" + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the specified service has been enabled to use authentication
|
||||
* tokens.
|
||||
*/
|
||||
public boolean svcEnabled(String hostName, String serviceName)
|
||||
{
|
||||
// First try to obtain the Map of enabled services for the host
|
||||
// tbd - Should we make this case insensitive?
|
||||
Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName);
|
||||
if (enabledSvcsConfigMap != null)
|
||||
{
|
||||
return enabledSvcsConfigMap.containsKey(serviceName);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the data associated with the authentication policy file
|
||||
* associated with the specified service.
|
||||
*/
|
||||
public byte[] getAuthPolicyFileDataForSvc(String hostName, String serviceName)
|
||||
{
|
||||
// First try to obtain the Map of enabled services for the host
|
||||
// tbd - Should we make this case insensitive?
|
||||
Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName);
|
||||
if (enabledSvcsConfigMap != null)
|
||||
{
|
||||
// Retrieve SvcConfigEntry for the service from the map for the host
|
||||
SvcConfigEntry svcConfigEntry = (SvcConfigEntry) enabledSvcsConfigMap.get(serviceName);
|
||||
if (svcConfigEntry != null)
|
||||
{
|
||||
return svcConfigEntry.m_authPolicyFileData;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the authentication token configuration associated with the
|
||||
* specified service.
|
||||
*/
|
||||
public AuthTokenConfig getAuthTokenConfig(String hostName, String serviceName)
|
||||
{
|
||||
// First try to obtain the Map of enabled services for the host
|
||||
// tbd - Should we make this case insensitive?
|
||||
Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName);
|
||||
if (enabledSvcsConfigMap != null)
|
||||
{
|
||||
// Retrieve SvcConfigEntry for the service from the map for the host
|
||||
SvcConfigEntry svcConfigEntry = (SvcConfigEntry) enabledSvcsConfigMap.get(serviceName);
|
||||
if (svcConfigEntry != null)
|
||||
{
|
||||
return svcConfigEntry.m_authTokenConfig;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the identity token configuration associated with the
|
||||
* specified service.
|
||||
*/
|
||||
public IdenTokenConfig getIdenTokenConfig(String hostName, String serviceName)
|
||||
{
|
||||
// First try to obtain the Map of enabled services for the host
|
||||
// tbd - Should we make this case insensitive?
|
||||
Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName);
|
||||
if (enabledSvcsConfigMap != null)
|
||||
{
|
||||
// Retrieve SvcConfigEntry for the service from the map for the host
|
||||
SvcConfigEntry svcConfigEntry = (SvcConfigEntry) enabledSvcsConfigMap.get(serviceName);
|
||||
if (svcConfigEntry != null)
|
||||
{
|
||||
return svcConfigEntry.m_idenTokenConfig;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* GetAuthPolicy Class.
|
||||
*
|
||||
* This class processes get authentication policy requests for a particular
|
||||
* service.
|
||||
*
|
||||
*/
|
||||
public class GetAuthPolicy implements RpcMethod
|
||||
{
|
||||
private SvcConfig m_svcConfig;
|
||||
private EnabledSvcsConfig m_enabledSvcsConfig;
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public GetAuthPolicy() throws Exception
|
||||
{
|
||||
// Nothing to do at this time
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the Rpc method.
|
||||
*/
|
||||
public void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception
|
||||
{
|
||||
m_svcConfig = svcConfig;
|
||||
m_enabledSvcsConfig = enabledSvcsConfig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process Rpc.
|
||||
*/
|
||||
public void invoke(InputStream inStream, PrintWriter out) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
System.err.println("GetAuthPolicy.invoke()");
|
||||
|
||||
// Read and parse the GetAuthPolicyReqMsg sent from the client
|
||||
GetAuthPolicyReqMsg getAuthPolicyReqMsg = new GetAuthPolicyReqMsg(inStream);
|
||||
|
||||
// Verify that the service is enabled
|
||||
if (m_enabledSvcsConfig.svcEnabled(getAuthPolicyReqMsg.getHostName(), getAuthPolicyReqMsg.getServiceName()))
|
||||
{
|
||||
// Get the auth policy for the service
|
||||
byte[] authPolicy = m_enabledSvcsConfig.getAuthPolicyFileDataForSvc(getAuthPolicyReqMsg.getHostName(),
|
||||
getAuthPolicyReqMsg.getServiceName());
|
||||
if (authPolicy != null)
|
||||
{
|
||||
// Write out the response
|
||||
GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpOkStatusMsg,
|
||||
ProtoDefs.httpOkStatusCode,
|
||||
new String(Base64Coder.encode(authPolicy)));
|
||||
out.println(getAuthPolicyRespMsg.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthPolicy.invoke()- authPolicy is null for enabled service: " + getAuthPolicyReqMsg.getServiceName());
|
||||
GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpServerErrorStatusMsg,
|
||||
ProtoDefs.httpServerErrorStatusCode);
|
||||
out.println(getAuthPolicyRespMsg.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The service has not been enabled to utilize our authentication tokens
|
||||
GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpNotFoundStatusMsg,
|
||||
ProtoDefs.httpNotFoundStatusCode);
|
||||
out.println(getAuthPolicyRespMsg.toString());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("GetAuthPolicy.invoke()- Exception: " + e.toString());
|
||||
|
||||
// Write out the response
|
||||
try
|
||||
{
|
||||
GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpServerErrorStatusMsg,
|
||||
ProtoDefs.httpServerErrorStatusCode);
|
||||
out.println(getAuthPolicyRespMsg.toString());
|
||||
}
|
||||
catch (Exception e2)
|
||||
{
|
||||
System.err.println("GetAuthPolicy.invoke()- Exception trying to construct response msg: " + e2.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the method id.
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return "GetAuthPolicy";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
* GetAuthPolicyReqMsg Class.
|
||||
*
|
||||
* This class deals with the message sent by Casa Client when requesting
|
||||
* authenication policy to authenticate an entity to a particular service.
|
||||
* The format of the the message is as follows:
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <get_auth_policy_req>
|
||||
* <service>service name</service>
|
||||
* <host>host name</host>
|
||||
* </get_auth_policy_req>
|
||||
*
|
||||
*/
|
||||
public class GetAuthPolicyReqMsg
|
||||
{
|
||||
|
||||
protected String m_serviceName = null;
|
||||
protected String m_hostName = null;
|
||||
|
||||
/*
|
||||
* Class for handling GetAuthPolicyReq msg parsing events.
|
||||
*/
|
||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
||||
{
|
||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
||||
private final static int AWAITING_ROOT_ELEMENT_END = 1;
|
||||
private final static int AWAITING_SERVICE_ELEMENT_START = 2;
|
||||
private final static int AWAITING_SERVICE_ELEMENT_END = 3;
|
||||
private final static int AWAITING_SERVICE_DATA = 4;
|
||||
private final static int AWAITING_HOST_ELEMENT_START = 5;
|
||||
private final static int AWAITING_HOST_ELEMENT_END = 6;
|
||||
private final static int AWAITING_HOST_DATA = 7;
|
||||
private final static int DONE_PARSING = 8;
|
||||
|
||||
private GetAuthPolicyReqMsg m_GetAuthPolicyReqMsg;
|
||||
private int m_state;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SAXHandler (GetAuthPolicyReqMsg GetAuthPolicyReqMsg)
|
||||
{
|
||||
super();
|
||||
|
||||
// Initialize our members
|
||||
m_GetAuthPolicyReqMsg = GetAuthPolicyReqMsg;
|
||||
m_state = AWAITING_ROOT_ELEMENT_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* endDocument() implementation.
|
||||
*/
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
// Verify that we obtained all of the required elements
|
||||
if (m_state != DONE_PARSING)
|
||||
{
|
||||
System.err.println("GetAuthPolicyReqMsg SAXHandler.endDocument()- Missing element");
|
||||
throw new SAXException("Missing element");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* startElement() implementation.
|
||||
*/
|
||||
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_ROOT_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SERVICE_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SERVICE_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.serviceElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SERVICE_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_HOST_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.hostElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_HOST_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endElement() immplementation.
|
||||
*/
|
||||
public void endElement (String uri, String name, String qName) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_ROOT_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = DONE_PARSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthPolicyReqMsg SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SERVICE_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.serviceElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_HOST_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthPolicyReqMsg SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_HOST_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.hostElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ROOT_ELEMENT_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthPolicyReqMsg SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* character() implementation.
|
||||
*/
|
||||
public void characters (char ch[], int start, int length) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_SERVICE_DATA:
|
||||
// Consume the data
|
||||
m_GetAuthPolicyReqMsg.m_serviceName = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SERVICE_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_HOST_DATA:
|
||||
// Consume the data
|
||||
m_GetAuthPolicyReqMsg.m_hostName = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_HOST_ELEMENT_END;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public GetAuthPolicyReqMsg (InputStream inStream) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse the GetAuthPolicyReqMsg
|
||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
||||
SAXHandler handler = new SAXHandler(this);
|
||||
xr.setContentHandler(handler);
|
||||
xr.setErrorHandler(handler);
|
||||
|
||||
InputSource source = new InputSource(inStream);
|
||||
xr.parse(source);
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
System.err.println("GetAuthPolicyReqMsg()- Parse exception: " + e.toString());
|
||||
throw new Exception("Protocol error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to get the service name.
|
||||
*/
|
||||
public String getServiceName() throws Exception
|
||||
{
|
||||
return m_serviceName;
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to get the host name.
|
||||
*/
|
||||
public String getHostName() throws Exception
|
||||
{
|
||||
return m_hostName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
/**
|
||||
* GetAuthPolicyRespMsg Class.
|
||||
*
|
||||
* This class deals with the message sent to the Casa Client as a
|
||||
* response to a get authentication token request. The format of
|
||||
* the message is as follows when the response includes an
|
||||
* authentication token:
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <get_auth_policy_resp>
|
||||
* <status><description>OK</description>200</status>
|
||||
* <auth_policy>authentication policy data</auth_policy>
|
||||
* </get_auth_policy_resp>
|
||||
*
|
||||
* The format of the message is as follows when the response does not
|
||||
* include an authentication token.
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <get_auth_policy_resp>
|
||||
* <status><description>status description</description>status code</status>
|
||||
* </get_auth_policy_resp>
|
||||
*
|
||||
* Plase note that the protocol utilizes the status codes defined
|
||||
* in the HTTP 1.1 Specification.
|
||||
*
|
||||
*/
|
||||
public class GetAuthPolicyRespMsg
|
||||
{
|
||||
|
||||
String m_msg;
|
||||
|
||||
/*
|
||||
* Constructor for a msg that does not include the authentication policy.
|
||||
*/
|
||||
public GetAuthPolicyRespMsg (
|
||||
String statusDescription,
|
||||
String statusCode) throws Exception
|
||||
{
|
||||
// Get a StringBuffer to help us with the construction of the message
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
// Start building the message
|
||||
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
|
||||
sb.append("<" + ProtoDefs.getAuthPolicyResponseElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.statusElementName + ">"
|
||||
+ "<" + ProtoDefs.descriptionElementName + ">" + statusDescription + "</" + ProtoDefs.descriptionElementName + ">"
|
||||
+ statusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
|
||||
sb.append("</" + ProtoDefs.getAuthPolicyResponseElementName + ">" + "\r\n");
|
||||
|
||||
// The message has now been built, save it.
|
||||
m_msg = sb.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor for a msg that includes the authentication policy.
|
||||
*/
|
||||
public GetAuthPolicyRespMsg (
|
||||
String statusDescription,
|
||||
String statusCode,
|
||||
String authPolicy) throws Exception
|
||||
{
|
||||
// Get a StringBuffer to help us with the construction of the message
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
// Start building the message
|
||||
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
|
||||
sb.append("<" + ProtoDefs.getAuthPolicyResponseElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.statusElementName + ">"
|
||||
+ "<" + ProtoDefs.descriptionElementName + ">" + ProtoDefs.httpOkStatusMsg + "</" + ProtoDefs.descriptionElementName + ">"
|
||||
+ ProtoDefs.httpOkStatusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.authPolicyElementName + ">" + authPolicy + "</" + ProtoDefs.authPolicyElementName + ">" + "\r\n");
|
||||
sb.append("</" + ProtoDefs.getAuthPolicyResponseElementName + ">" + "\r\n");
|
||||
|
||||
// The message has now been built, save it.
|
||||
m_msg = sb.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containing the GetAuthPolicyRespMsg.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return m_msg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
* GetAuthTokReqMsg Class.
|
||||
*
|
||||
* This class deals with the message sent by Casa Client when requesting
|
||||
* a token to authenticate an entity to a particular service. The format of
|
||||
* the message is as follows:
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <get_auth_token_req>
|
||||
* <service>service name</service>
|
||||
* <host>host name</host>
|
||||
* <session_token>session token data</session_token>
|
||||
* </get_auth_token_req>
|
||||
*
|
||||
*/
|
||||
public class GetAuthTokReqMsg
|
||||
{
|
||||
|
||||
protected String m_serviceName = null;
|
||||
protected String m_hostName = null;
|
||||
protected String m_sessionToken = null;
|
||||
|
||||
/*
|
||||
* Class for handling GetAuthTokReq msg parsing events.
|
||||
*/
|
||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
||||
{
|
||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
||||
private final static int AWAITING_ROOT_ELEMENT_END = 1;
|
||||
private final static int AWAITING_SERVICE_ELEMENT_START = 2;
|
||||
private final static int AWAITING_SERVICE_ELEMENT_END = 3;
|
||||
private final static int AWAITING_SERVICE_DATA = 4;
|
||||
private final static int AWAITING_HOST_ELEMENT_START = 5;
|
||||
private final static int AWAITING_HOST_ELEMENT_END = 6;
|
||||
private final static int AWAITING_HOST_DATA = 7;
|
||||
private final static int AWAITING_SESSION_TOKEN_ELEMENT_START = 8;
|
||||
private final static int AWAITING_SESSION_TOKEN_ELEMENT_END = 9;
|
||||
private final static int AWAITING_SESSION_TOKEN_DATA = 10;
|
||||
private final static int DONE_PARSING = 11;
|
||||
|
||||
private GetAuthTokReqMsg m_GetAuthTokReqMsg;
|
||||
private int m_state;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SAXHandler (GetAuthTokReqMsg GetAuthTokReqMsg)
|
||||
{
|
||||
super();
|
||||
|
||||
// Initialize our members
|
||||
m_GetAuthTokReqMsg = GetAuthTokReqMsg;
|
||||
m_state = AWAITING_ROOT_ELEMENT_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* endDocument() implementation.
|
||||
*/
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
// Verify that we obtained all of the required elements
|
||||
if (m_state != DONE_PARSING)
|
||||
{
|
||||
System.err.println("GetAuthTokReqMsg SAXHandler.endDocument()- Missing element");
|
||||
throw new SAXException("Missing element");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* startElement() implementation.
|
||||
*/
|
||||
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_ROOT_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.getAuthTokRequestElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SERVICE_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SERVICE_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.serviceElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SERVICE_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_HOST_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.hostElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_HOST_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AWAITING_SESSION_TOKEN_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.sessionTokenElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SESSION_TOKEN_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endElement() immplementation.
|
||||
*/
|
||||
public void endElement (String uri, String name, String qName) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_ROOT_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.getAuthTokRequestElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = DONE_PARSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SERVICE_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.serviceElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_HOST_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_HOST_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.hostElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SESSION_TOKEN_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SESSION_TOKEN_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.sessionTokenElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ROOT_ELEMENT_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* character() implementation.
|
||||
*/
|
||||
public void characters (char ch[], int start, int length) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_SERVICE_DATA:
|
||||
// Consume the data
|
||||
m_GetAuthTokReqMsg.m_serviceName = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SERVICE_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_HOST_DATA:
|
||||
// Consume the data
|
||||
m_GetAuthTokReqMsg.m_hostName = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_HOST_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_SESSION_TOKEN_DATA:
|
||||
// Consume the data
|
||||
m_GetAuthTokReqMsg.m_sessionToken = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SESSION_TOKEN_ELEMENT_END;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public GetAuthTokReqMsg (InputStream inStream) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse the GetAuthTokReqMsg
|
||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
||||
SAXHandler handler = new SAXHandler(this);
|
||||
xr.setContentHandler(handler);
|
||||
xr.setErrorHandler(handler);
|
||||
|
||||
InputSource source = new InputSource(inStream);
|
||||
xr.parse(source);
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
System.err.println("GetAuthTokReqMsg()- Parse exception: " + e.toString());
|
||||
throw new Exception("Protocol error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to get the service name.
|
||||
*/
|
||||
public String getServiceName() throws Exception
|
||||
{
|
||||
return m_serviceName;
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to get the host name.
|
||||
*/
|
||||
public String getHostName() throws Exception
|
||||
{
|
||||
return m_hostName;
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to get the session token.
|
||||
*/
|
||||
public String getSessionToken() throws Exception
|
||||
{
|
||||
return m_sessionToken;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
/**
|
||||
* GetAuthTokRespMsg Class.
|
||||
*
|
||||
* This class deals with the message sent to the Casa Client as a
|
||||
* response to a get authentication token request. The format of
|
||||
* the message is as follows when the response includes an
|
||||
* authentication token:
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <get_auth_tok_resp>
|
||||
* <status><description>OK</description>200</status>
|
||||
* <auth_token><lifetime>lifetime value</lifetime>authentication token data</auth_token>
|
||||
* </get_auth_tok_resp>
|
||||
*
|
||||
* The format of the message is as follows when the response does not
|
||||
* include an authentication token.
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <get_auth_tok_resp>
|
||||
* <status><description>status description</description>status code</status>
|
||||
* </get_auth_tok_resp>
|
||||
*
|
||||
* Plase note that the protocol utilizes the status codes defined
|
||||
* in the HTTP 1.1 Specification.
|
||||
*
|
||||
*/
|
||||
public class GetAuthTokRespMsg
|
||||
{
|
||||
|
||||
String m_msg;
|
||||
|
||||
/*
|
||||
* Constructor for a msg that does not include the authentication token.
|
||||
*/
|
||||
public GetAuthTokRespMsg (
|
||||
String statusDescription,
|
||||
String statusCode) throws Exception
|
||||
{
|
||||
// Get a StringBuffer to help us with the construction of the message
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
// Start building the message
|
||||
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
|
||||
sb.append("<" + ProtoDefs.getAuthTokResponseElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.statusElementName + ">"
|
||||
+ "<" + ProtoDefs.descriptionElementName + ">" + statusDescription + "</" + ProtoDefs.descriptionElementName + ">"
|
||||
+ statusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
|
||||
sb.append("</" + ProtoDefs.getAuthTokResponseElementName + ">" + "\r\n");
|
||||
|
||||
// The message has now been built, save it.
|
||||
m_msg = sb.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor for a msg that includes the authentication token.
|
||||
*/
|
||||
public GetAuthTokRespMsg (
|
||||
String statusDescription,
|
||||
String statusCode,
|
||||
String authToken,
|
||||
String authTokenLifetime) throws Exception
|
||||
{
|
||||
// Get a StringBuffer to help us with the construction of the message
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
// Start building the message
|
||||
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
|
||||
sb.append("<" + ProtoDefs.getAuthTokResponseElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.statusElementName + ">"
|
||||
+ "<" + ProtoDefs.descriptionElementName + ">" + ProtoDefs.httpOkStatusMsg + "</" + ProtoDefs.descriptionElementName + ">"
|
||||
+ ProtoDefs.httpOkStatusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.authTokenElementName + ">"
|
||||
+ "<" + ProtoDefs.lifetimeElementName + ">" + authTokenLifetime + "</" + ProtoDefs.lifetimeElementName + ">"
|
||||
+ authToken + "</" + ProtoDefs.authTokenElementName + ">" + "\r\n");
|
||||
sb.append("</" + ProtoDefs.getAuthTokResponseElementName + ">" + "\r\n");
|
||||
|
||||
// The message has now been built, save it.
|
||||
m_msg = sb.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containing the GetAuthTokRespMsg.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return m_msg;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* GetAuthToken Class.
|
||||
*
|
||||
* This class processes requests for tokens to authenticate an entity
|
||||
* to a particular service.
|
||||
*
|
||||
*/
|
||||
public class GetAuthToken implements RpcMethod
|
||||
{
|
||||
private SvcConfig m_svcConfig;
|
||||
private EnabledSvcsConfig m_enabledSvcsConfig;
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public GetAuthToken() throws Exception
|
||||
{
|
||||
// Nothing to do at this time
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the Rpc method.
|
||||
*/
|
||||
public void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception
|
||||
{
|
||||
m_svcConfig = svcConfig;
|
||||
m_enabledSvcsConfig = enabledSvcsConfig;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process Rpc.
|
||||
*/
|
||||
public void invoke(InputStream inStream, PrintWriter out) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
System.err.println("GetAuthToken.invoke()");
|
||||
|
||||
// Parse the GetAuthTokReqMsg sent from the client
|
||||
GetAuthTokReqMsg getAuthTokReqMsg = new GetAuthTokReqMsg(inStream);
|
||||
|
||||
// Verify that the service is enabled
|
||||
if (m_enabledSvcsConfig.svcEnabled(getAuthTokReqMsg.getHostName(),
|
||||
getAuthTokReqMsg.getServiceName()))
|
||||
{
|
||||
// Now create a session token (This validates the session token provided).
|
||||
SessionToken sessionToken = new SessionToken(getAuthTokReqMsg.getSessionToken());
|
||||
|
||||
try
|
||||
{
|
||||
// Create the Authentication Token
|
||||
AuthToken authToken = new AuthToken(sessionToken.getIdentId(),
|
||||
sessionToken.getRealm(),
|
||||
getAuthTokReqMsg.getServiceName(),
|
||||
getAuthTokReqMsg.getHostName(),
|
||||
m_svcConfig,
|
||||
m_enabledSvcsConfig);
|
||||
|
||||
// Write out the response
|
||||
GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpOkStatusMsg,
|
||||
ProtoDefs.httpOkStatusCode,
|
||||
authToken.toString(),
|
||||
authToken.getLifetime());
|
||||
out.println(getAuthTokRespMsg.toString());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("GetAuthToken.invoke()- Exception: " + e.toString());
|
||||
|
||||
// Write out the response
|
||||
try
|
||||
{
|
||||
GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpUnauthorizedStatusMsg,
|
||||
ProtoDefs.httpUnauthorizedStatusCode);
|
||||
out.println(getAuthTokRespMsg.toString());
|
||||
}
|
||||
catch (Exception e2)
|
||||
{
|
||||
System.err.println("GetAuthToken.invoke()- Exception trying to construct response msg: " + e2.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The service has not been enabled to utilize our authentication tokens
|
||||
GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpNotFoundStatusMsg,
|
||||
ProtoDefs.httpNotFoundStatusCode);
|
||||
out.println(getAuthTokRespMsg.toString());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("GetAuthToken.invoke()- Exception: " + e.toString());
|
||||
|
||||
// Write out the response
|
||||
try
|
||||
{
|
||||
GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpServerErrorStatusMsg,
|
||||
ProtoDefs.httpServerErrorStatusCode);
|
||||
out.println(getAuthTokRespMsg.toString());
|
||||
}
|
||||
catch (Exception e2)
|
||||
{
|
||||
System.err.println("GetAuthToken.invoke()- Exception trying to construct response msg: " + e2.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the method id.
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return "GetAuthToken";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
* IdenTokenConfig Class.
|
||||
*
|
||||
* This class obtains and maintains identity token configuration.
|
||||
*
|
||||
*/
|
||||
public class IdenTokenConfig
|
||||
{
|
||||
// Well known identity token configuration settings
|
||||
public final static String EncryptAttributes = "EncryptAttributes";
|
||||
public final static String Attributes = "Attributes";
|
||||
|
||||
// Default configuration values
|
||||
private String m_defaultEncryptAttributesValue = "false";
|
||||
private String m_defaultAttributesValue = "sn";
|
||||
|
||||
private Map m_tokenSettingsMap;
|
||||
private String[] m_identityAttributes;
|
||||
|
||||
/*
|
||||
* Class for handling parsing events.
|
||||
*/
|
||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
||||
{
|
||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
||||
private final static int AWAITING_SETTING_ELEMENT_START = 1;
|
||||
private final static int AWAITING_SETTING_ELEMENT_DATA = 2;
|
||||
private final static int AWAITING_SETTING_ELEMENT_END = 3;
|
||||
private final static int DONE_PARSING = 4;
|
||||
|
||||
private final static String m_rootElementName = "settings";
|
||||
|
||||
private Map m_keyMap;
|
||||
private int m_state;
|
||||
private String m_currentKey;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SAXHandler(Map keyMap)
|
||||
{
|
||||
super();
|
||||
|
||||
// Initialize our members
|
||||
m_keyMap = keyMap;
|
||||
m_state = AWAITING_ROOT_ELEMENT_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* endDocument() implementation.
|
||||
*/
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
// Verify that we are not in an invalid state
|
||||
if (m_state != DONE_PARSING)
|
||||
{
|
||||
System.err.println("IdenTokenConfig SAXHandler.endDocument()- Invalid state" + m_state);
|
||||
throw new SAXException("Invalid state at endDocument");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* startElement() implementation.
|
||||
*/
|
||||
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
case AWAITING_ROOT_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (m_rootElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("IdenTokenConfig SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SETTING_ELEMENT_START:
|
||||
// Keep track of the key name
|
||||
m_currentKey = qName;
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_DATA;
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("IdenTokenConfig SAXHandler.startElement()- Invalid state " + m_state);
|
||||
throw new SAXException("Invalid state at startElement");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endElement() immplementation.
|
||||
*/
|
||||
public void endElement (String uri, String name, String qName) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
case AWAITING_SETTING_ELEMENT_DATA:
|
||||
case AWAITING_SETTING_ELEMENT_END:
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_START;
|
||||
break;
|
||||
|
||||
case AWAITING_SETTING_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (m_rootElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = DONE_PARSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("IdenTokenConfig SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("IdenTokenConfig SAXHandler.endElement()- Invalid state " + m_state);
|
||||
throw new SAXException("Invalid state at endElement");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* character() implementation.
|
||||
*/
|
||||
public void characters (char ch[], int start, int length) throws SAXException
|
||||
{
|
||||
// Consume the data if in the right state
|
||||
if (m_state == AWAITING_SETTING_ELEMENT_DATA)
|
||||
{
|
||||
// Consume the data and add the key to map
|
||||
// tbd - Add code to aggregate attributes specified as multiple elements
|
||||
m_keyMap.put(m_currentKey, new String(ch, start, length));
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor which sets default configuration values.
|
||||
*/
|
||||
public IdenTokenConfig() throws Exception
|
||||
{
|
||||
System.err.println("IdenTokenConfig()- Default");
|
||||
|
||||
// Create a map to keep track of the token settings
|
||||
m_tokenSettingsMap = new HashMap();
|
||||
|
||||
// Set the default settings in our map
|
||||
m_tokenSettingsMap.put(Attributes, m_defaultAttributesValue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public IdenTokenConfig(String idenTokenSettingsFileName) throws Exception
|
||||
{
|
||||
System.err.println("IdenTokenConfig()-");
|
||||
|
||||
// Create a map to keep track of the token settings
|
||||
m_tokenSettingsMap = new HashMap();
|
||||
|
||||
try
|
||||
{
|
||||
// Get an input stream to read from the token settings file
|
||||
File f = new File(idenTokenSettingsFileName);
|
||||
FileInputStream inStream = new FileInputStream(f);
|
||||
|
||||
// Parse the file
|
||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
||||
SAXHandler handler = new SAXHandler(m_tokenSettingsMap);
|
||||
xr.setContentHandler(handler);
|
||||
xr.setErrorHandler(handler);
|
||||
|
||||
InputSource source = new InputSource(inStream);
|
||||
xr.parse(source);
|
||||
|
||||
inStream.close();
|
||||
|
||||
// Process the specified attributes
|
||||
if (m_tokenSettingsMap.containsKey(Attributes) == false)
|
||||
{
|
||||
System.err.println("IdenTokenConfig()- Attributes not configured, defaulting them.");
|
||||
m_tokenSettingsMap.put(Attributes, m_defaultAttributesValue);
|
||||
}
|
||||
String attributes = (String) m_tokenSettingsMap.get(Attributes);
|
||||
m_identityAttributes = attributes.split(",");
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
System.err.println("IdenTokenConfig()- " + idenTokenSettingsFileName + " format error, exception: " + e.toString());
|
||||
throw new Exception("IdenTokenConfig()- authtoken.settings format error");
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("IdenTokenConfig()- SecurityException accessing " + idenTokenSettingsFileName + " Exception=" + e.toString());
|
||||
throw new Exception("IdenTokenConfig()- Not able to access file");
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
System.err.println("IdenTokenConfig()- File " + idenTokenSettingsFileName + " not found");
|
||||
throw new Exception("IdenTokenConfig()- File not found");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println("IdenTokenConfig()- IOException accessing " + idenTokenSettingsFileName + " Exception=" + e.toString());
|
||||
throw new Exception("IdenTokenConfig()- Read error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the value associated with the specified setting.
|
||||
*/
|
||||
public String getSetting(String settingName) throws Exception
|
||||
{
|
||||
// Try to find the setting in our map
|
||||
String value = (String) m_tokenSettingsMap.get(settingName);
|
||||
if (value == null)
|
||||
{
|
||||
System.err.println("IdenTokenConfig.getSetting()- Did not find setting " + settingName);
|
||||
|
||||
// The setting is not in our map, check if it is one to
|
||||
// which we have defaults.
|
||||
if (settingName.equals(EncryptAttributes) == true)
|
||||
{
|
||||
value = m_defaultEncryptAttributesValue;
|
||||
System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value);
|
||||
|
||||
// Add the key to the map so that it can be found quicker next time
|
||||
m_tokenSettingsMap.put(EncryptAttributes, m_defaultEncryptAttributesValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("IdenTokenConfig.getSetting()- Found setting " + settingName);
|
||||
System.err.println("IdenTokenConfig.getSetting()- Setting value = " + value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the identity attributes that must be included in the token.
|
||||
*/
|
||||
public String[] getAttributes() throws Exception
|
||||
{
|
||||
return m_identityAttributes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
/*
|
||||
* IdentityToken Interface.
|
||||
*
|
||||
* This is the interface implemented by Identity Token Providers.
|
||||
*/
|
||||
public interface IdentityToken
|
||||
{
|
||||
/*
|
||||
* Initialize the token with parameters.
|
||||
*/
|
||||
void initialize(String identityId,
|
||||
String sourceName,
|
||||
String targetService,
|
||||
String targetHost,
|
||||
SvcConfig svcConfig) throws Exception;
|
||||
|
||||
/*
|
||||
* Initialize the token object with encoded token string.
|
||||
*/
|
||||
void initialize(String encodedToken) throws Exception;
|
||||
|
||||
/*
|
||||
* Returns encoded token string.
|
||||
*
|
||||
* IMPORTANT: The token string can not contain the substring "]]>"
|
||||
* within it.
|
||||
*/
|
||||
String getEncodedToken() throws Exception;
|
||||
|
||||
/*
|
||||
* Returns a string containing the identity token provider type.
|
||||
*/
|
||||
String getProviderType() throws Exception;
|
||||
|
||||
/*
|
||||
* Returns a string containing the identity id.
|
||||
*/
|
||||
String getIdentityId() throws Exception;
|
||||
|
||||
/*
|
||||
* Returns a string containing the name associated with the
|
||||
* identity source.
|
||||
*/
|
||||
String getSourceName() throws Exception;
|
||||
|
||||
/*
|
||||
* Returns a string containing the url associated with the
|
||||
* identity source.
|
||||
*/
|
||||
String getSourceUrl() throws Exception;
|
||||
|
||||
/*
|
||||
* Returns a string containing the name of the targeted service.
|
||||
*/
|
||||
String getTargetService() throws Exception;
|
||||
|
||||
/*
|
||||
* Returns a string containig the name of the host where the
|
||||
* targeted service resides.
|
||||
*/
|
||||
String getTargetHost() throws Exception;
|
||||
|
||||
/*
|
||||
* Returns the attributes of the identity.
|
||||
*/
|
||||
javax.naming.directory.Attributes getAttributes() throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.BasicAttribute;
|
||||
import javax.naming.directory.BasicAttributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import javax.naming.directory.SearchResult;
|
||||
import javax.naming.directory.SearchControls;
|
||||
|
||||
import org.ietf.jgss.GSSContext;
|
||||
import org.ietf.jgss.GSSCredential;
|
||||
import org.ietf.jgss.GSSException;
|
||||
import org.ietf.jgss.GSSManager;
|
||||
import org.ietf.jgss.GSSName;
|
||||
import org.ietf.jgss.Oid;
|
||||
|
||||
import org.bandit.ia.IAContext;
|
||||
|
||||
/**
|
||||
* Krb5Authenticate Class.
|
||||
*
|
||||
* This class implementes an authentication mechanism for
|
||||
* the processing of authentication requests utilizing a
|
||||
* Kerberos5 token.
|
||||
*
|
||||
*/
|
||||
public class Krb5Authenticate implements AuthMechanism, Serializable
|
||||
{
|
||||
private static final String ServicePrincipalNameSetting = "ServicePrincipalName";
|
||||
|
||||
private SvcConfig m_svcConfig;
|
||||
private AuthMechConfig m_mechConfig;
|
||||
|
||||
/*
|
||||
* GSS Long Lived variables
|
||||
*/
|
||||
protected GSSManager m_manager;
|
||||
protected Oid m_krb5;
|
||||
protected GSSName m_svcName;
|
||||
protected GSSCredential m_credential;
|
||||
|
||||
/*
|
||||
* Krb5 Token Class.
|
||||
*/
|
||||
private class Krb5Token
|
||||
{
|
||||
private String m_principalName = "";
|
||||
|
||||
/*
|
||||
* The format of the Krb5 token is as follows:
|
||||
*
|
||||
* Base64.encode(GSS-API Token data));
|
||||
*/
|
||||
public Krb5Token(String encodedToken, Krb5Authenticate parent) throws Exception
|
||||
{
|
||||
// Decode the token
|
||||
char[] tokenChars = new char[encodedToken.length()];
|
||||
encodedToken.getChars(0, tokenChars.length, tokenChars, 0);
|
||||
byte[] tokenBytes = Base64Coder.decode(tokenChars);
|
||||
|
||||
try
|
||||
{
|
||||
// Create a context and validate the token
|
||||
GSSContext context = parent.m_manager.createContext(parent.m_credential);
|
||||
System.err.println("tokenLength = " + tokenBytes.length);
|
||||
context.acceptSecContext(tokenBytes, 0, tokenBytes.length);
|
||||
|
||||
// Save the principal name of the authenticated entity
|
||||
GSSName principalName = context.getSrcName();
|
||||
m_principalName = principalName.toString();
|
||||
|
||||
// Clean up
|
||||
context.dispose();
|
||||
}
|
||||
catch (GSSException e)
|
||||
{
|
||||
System.err.println("Krb5Authenticate Krb5Token()- GSS Exception caught: " + e.getLocalizedMessage());
|
||||
throw new Exception("Authentication Failure");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the name of the authenticated principal
|
||||
*/
|
||||
public String getPrincipalName()
|
||||
{
|
||||
return m_principalName;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public Krb5Authenticate() throws Exception
|
||||
{
|
||||
// Nothing to do at this time
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the mechanism.
|
||||
*/
|
||||
public void init(SvcConfig svcConfig, AuthMechConfig mechConfig) throws Exception
|
||||
{
|
||||
m_svcConfig = svcConfig;
|
||||
m_mechConfig = mechConfig;
|
||||
|
||||
String servicePrincipal = mechConfig.getSetting(ServicePrincipalNameSetting);
|
||||
if (servicePrincipal != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Initalize our GSS variables
|
||||
//
|
||||
// Get an instance of the default GSSManager
|
||||
m_manager = GSSManager.getInstance();
|
||||
|
||||
// Create an OID specifying the Krb5 mechanism
|
||||
m_krb5 = new Oid("1.2.840.113554.1.2.2");
|
||||
|
||||
// Create our host based service name
|
||||
m_svcName = m_manager.createName(servicePrincipal,
|
||||
GSSName.NT_HOSTBASED_SERVICE,
|
||||
m_krb5);
|
||||
|
||||
// Now acquire our credentials
|
||||
m_credential = m_manager.createCredential(m_svcName,
|
||||
GSSCredential.INDEFINITE_LIFETIME,
|
||||
m_krb5,
|
||||
GSSCredential.ACCEPT_ONLY);
|
||||
}
|
||||
catch (GSSException e)
|
||||
{
|
||||
System.err.println("Krb5Authenticate()- GSS Exception caught: " + e.getLocalizedMessage());
|
||||
throw new Exception("Failed to instantiate needed GSS objects");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Krb5Authenticate()- Service Principal Name not configured");
|
||||
throw new Exception("Service Principal Name not configured");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* invoke() implementation.
|
||||
*/
|
||||
public String invoke(AuthReqMsg authReqMsg) throws Exception
|
||||
{
|
||||
String identId = null;
|
||||
|
||||
try
|
||||
{
|
||||
System.err.println("Krb5Authenticate.invoke()");
|
||||
|
||||
// Now parse the Kerberos Token
|
||||
Krb5Token krb5Token = new Krb5Token(authReqMsg.getAuthMechToken(), this);
|
||||
|
||||
// Open a directory context and use it to identify the users
|
||||
// associated with the specified surname.
|
||||
Hashtable env = new Hashtable();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
|
||||
env.put(IAContext.IA_REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
|
||||
env.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm());
|
||||
|
||||
DirContext ctx = new InitialDirContext(env);
|
||||
|
||||
// Now search for a user with a matching kerberos principal name.
|
||||
//
|
||||
// Set up a search control so that the search is scoped to the sub-tree
|
||||
SearchControls controls = new SearchControls();
|
||||
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||
|
||||
// Obtain the start search context - tbd - this will be removed once the functionality flows into Bandit
|
||||
String searchContext = m_svcConfig.getSetting(SvcConfig.StartSearchContext);
|
||||
if (searchContext == null)
|
||||
{
|
||||
// A start search context was not configured, start from the root.
|
||||
searchContext = "";
|
||||
}
|
||||
|
||||
// Perform the search
|
||||
NamingEnumeration answer = ctx.search(searchContext,
|
||||
"(krbPrincipalName={0})",
|
||||
new String[] {krb5Token.getPrincipalName()},
|
||||
controls);
|
||||
|
||||
// Proceed based on the result of the search
|
||||
if (answer.hasMore())
|
||||
{
|
||||
// The search succeeded, set the identity id.
|
||||
SearchResult sr = (SearchResult)answer.next();
|
||||
if (searchContext.equals(""))
|
||||
{
|
||||
identId = sr.getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
identId = sr.getName() + "," + searchContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
// Log the error
|
||||
System.err.println("Krb5Authenticate.invoke()- NamingException: " + e.getExplanation());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Krb5Authenticate.invoke()- Exception: " + e.toString());
|
||||
}
|
||||
|
||||
// Return the authentication result
|
||||
return identId;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the mechanism id.
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return "Krb5Authenticate";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<description>This is the authentication mechanism for the Krb5Authenticate scheme. The Krb5Authenticate scheme authenticates entities using Kerberos-V tokens.</description>
|
||||
<ClassName>com.novell.casa.authtoksvc.Krb5Authenticate</ClassName>
|
||||
<RelativeClassPath>WEB-INF/classes</RelativeClassPath>
|
||||
<ServicePrincipalName>Specify the service's kerberos principal name</ServicePrincipalName>
|
||||
</settings>
|
||||
@@ -0,0 +1,86 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
/*
|
||||
* ProDefs Class.
|
||||
*
|
||||
* This class contains constants utilized in the Casa Client/Server
|
||||
* protocol.
|
||||
*
|
||||
*/
|
||||
public class ProtoDefs
|
||||
{
|
||||
|
||||
/*
|
||||
* XML Declaration used in the Casa Client/Server protocol
|
||||
*/
|
||||
public final static String xmlDeclaration = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
|
||||
|
||||
/*
|
||||
* XML Element Name Constants for the documents exchanged between the
|
||||
* Casa Client and the Casa Server.
|
||||
*/
|
||||
public final static String authRequestElementName = "auth_req";
|
||||
public final static String authResponseElementName = "auth_resp";
|
||||
public final static String getAuthPolicyRequestElementName = "get_auth_policy_req";
|
||||
public final static String getAuthPolicyResponseElementName = "get_auth_policy_resp";
|
||||
public final static String getAuthTokRequestElementName = "get_auth_tok_req";
|
||||
public final static String getAuthTokResponseElementName = "get_auth_tok_resp";
|
||||
public final static String authMechTokenElementName = "auth_mech_token";
|
||||
public final static String statusElementName = "status";
|
||||
public final static String sessionTokenElementName = "session_token";
|
||||
public final static String authTokenElementName = "auth_token";
|
||||
public final static String authPolicyElementName = "auth_policy";
|
||||
public final static String identTokenElementName = "ident_token";
|
||||
public final static String lifetimeElementName = "lifetime";
|
||||
public final static String signatureElementName = "signature";
|
||||
public final static String typeElementName = "type";
|
||||
public final static String descriptionElementName = "description";
|
||||
public final static String serviceElementName = "service";
|
||||
public final static String hostElementName = "host";
|
||||
public final static String identIdElementName = "ident_id";
|
||||
public final static String realmElementName = "realm";
|
||||
public final static String authSourceElementName = "auth_source";
|
||||
public final static String mechanismElementName = "mechanism";
|
||||
public final static String mechanismInfoElementName = "mechanism_info";
|
||||
|
||||
/*
|
||||
* Configurable operating parameters
|
||||
*/
|
||||
public String sessionTokenLifetime = "360";
|
||||
|
||||
/*
|
||||
* HTTP Status Codes and Messages
|
||||
*/
|
||||
public final static String httpOkStatusCode = "200";
|
||||
public final static String httpOkStatusMsg = "OK";
|
||||
public final static String httpUnauthorizedStatusCode = "401";
|
||||
public final static String httpUnauthorizedStatusMsg = "Unauthorized";
|
||||
public final static String httpNotFoundStatusCode = "404";
|
||||
public final static String httpNotFoundStatusMsg = "Not Found";
|
||||
public final static String httpServerErrorStatusCode = "500";
|
||||
public final static String httpServerErrorStatusMsg = "Internal Server Error";
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringReader;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.naming.directory.BasicAttribute;
|
||||
import javax.naming.directory.BasicAttributes;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.SearchResult;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.bandit.ia.IAContext;
|
||||
|
||||
|
||||
/**
|
||||
* PwdAuthenticate Class.
|
||||
*
|
||||
* This class implementes an authentication mechanism for
|
||||
* the processing of authentication requests utilizing a
|
||||
* username/password token.
|
||||
*
|
||||
*/
|
||||
public class PwdAuthenticate implements AuthMechanism, Serializable
|
||||
{
|
||||
private SvcConfig m_svcConfig;
|
||||
private AuthMechConfig m_mechConfig;
|
||||
|
||||
/*
|
||||
* Password Token Class.
|
||||
*/
|
||||
private class PwToken
|
||||
{
|
||||
private String m_username = "";
|
||||
private String m_password = "";
|
||||
|
||||
/*
|
||||
* The format of the Pw token is as follows:
|
||||
*
|
||||
* Base64.encode(new String("username\r\n" + "password\r\n"));
|
||||
*/
|
||||
public PwToken(String encodedToken) throws IOException
|
||||
{
|
||||
// Decode the token
|
||||
String token = Base64Coder.decode(encodedToken);
|
||||
|
||||
BufferedReader tokenReader = new BufferedReader(new StringReader(token));
|
||||
|
||||
// The second line contains the "username"
|
||||
m_username = tokenReader.readLine();
|
||||
|
||||
// The third line contains the "password"
|
||||
m_password = tokenReader.readLine();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the username
|
||||
*/
|
||||
public String getUsername()
|
||||
{
|
||||
return m_username;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the password
|
||||
*/
|
||||
public String getPassword()
|
||||
{
|
||||
return m_password;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public PwdAuthenticate() throws Exception
|
||||
{
|
||||
// Nothing to do at this time
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the mechanism.
|
||||
*/
|
||||
public void init(SvcConfig svcConfig, AuthMechConfig mechConfig) throws Exception
|
||||
{
|
||||
m_svcConfig = svcConfig;
|
||||
m_mechConfig = mechConfig;
|
||||
}
|
||||
|
||||
/*
|
||||
* invoke() implementation.
|
||||
*/
|
||||
public String invoke(AuthReqMsg authReqMsg) throws Exception
|
||||
{
|
||||
String identId = null;
|
||||
|
||||
try
|
||||
{
|
||||
System.err.println("PwdAuthenticate.invoke()");
|
||||
|
||||
// Now parse the PW Token
|
||||
PwToken pwToken = new PwToken(authReqMsg.getAuthMechToken());
|
||||
|
||||
// Open a directory context and use it to identify the users
|
||||
// associated with the specified surname.
|
||||
Hashtable env = new Hashtable();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
|
||||
env.put(IAContext.IA_REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
|
||||
env.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm());
|
||||
|
||||
DirContext ctx = new InitialDirContext(env);
|
||||
|
||||
// Now search for a user with a matching surname.
|
||||
//
|
||||
// Set up a search control so that the search is scoped to the sub-tree
|
||||
SearchControls controls = new SearchControls();
|
||||
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
|
||||
|
||||
// Obtain the start search context - tbd - this will be removed once the functionality flows into Bandit
|
||||
String searchContext = m_svcConfig.getSetting(SvcConfig.StartSearchContext);
|
||||
if (searchContext == null)
|
||||
{
|
||||
// A start search context was not configured, start from the root.
|
||||
searchContext = "";
|
||||
}
|
||||
|
||||
// Perform the search
|
||||
NamingEnumeration answer = ctx.search(searchContext,
|
||||
"(cn={0})",
|
||||
new String[] {pwToken.getUsername()},
|
||||
controls);
|
||||
|
||||
// Enumerate through the users returned checking the password
|
||||
while (answer.hasMore())
|
||||
{
|
||||
SearchResult sr = (SearchResult)answer.next();
|
||||
|
||||
// Open a directory context for the user as a way of verifying its password
|
||||
try
|
||||
{
|
||||
Hashtable env2 = new Hashtable();
|
||||
env2.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
|
||||
env2.put(IAContext.IA_REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
|
||||
env2.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm());
|
||||
env2.put(Context.SECURITY_AUTHENTICATION, "simple");
|
||||
env2.put(Context.SECURITY_PRINCIPAL, sr.getName());
|
||||
env2.put(Context.SECURITY_CREDENTIALS, pwToken.getPassword());
|
||||
|
||||
if ((new InitialDirContext(env2)) != null)
|
||||
{
|
||||
// The password must be valid, set the identity Id.
|
||||
if (searchContext.equals(""))
|
||||
{
|
||||
identId = sr.getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
identId = sr.getName() + "," + searchContext;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
System.err.println("PwdAuthenticate.invoke()- NamingException: " + e.getExplanation());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
// Log the error
|
||||
System.err.println("PwdAuthenticate.invoke()- NamingException on Proxy User: " + e.getExplanation());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("PwdAuthenticate.invoke()- Exception: " + e.toString());
|
||||
}
|
||||
|
||||
// Return the authentication result
|
||||
return identId;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the mechanism id.
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return "PwdAuthenticate";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<description>This is the authentication mechanism for the PwdAuthenticate scheme. The PwdAuthenticate scheme authenticates entities using username/password tokens.</description>
|
||||
<ClassName>com.novell.casa.authtoksvc.PwdAuthenticate</ClassName>
|
||||
<RelativeClassPath>WEB-INF/classes</RelativeClassPath>
|
||||
</settings>
|
||||
@@ -0,0 +1,285 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Rpc Servlet Class.
|
||||
*
|
||||
* This class processes Rpcs to the Authentication Token Service.
|
||||
*
|
||||
*/
|
||||
public class Rpc extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet
|
||||
{
|
||||
private static final long serialVersionUID = -8264027868130334613L;
|
||||
|
||||
private String m_appFolderPath = null;
|
||||
private String m_configFolderPath = null;
|
||||
|
||||
protected ReconfigureThread m_reconfigureThread = null;
|
||||
protected int m_reconfigureInterval; // seconds
|
||||
|
||||
private Map m_methodsMap;
|
||||
|
||||
/*
|
||||
* Reconfigure Thread Class.
|
||||
*
|
||||
* This class implements a runnable thread that reconfigures an Rpc Servlet instance.
|
||||
*
|
||||
*/
|
||||
private class ReconfigureThread implements Runnable
|
||||
{
|
||||
private Rpc m_rpc;
|
||||
private Thread m_thread;
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public ReconfigureThread (Rpc rpc)
|
||||
{
|
||||
m_rpc = rpc;
|
||||
m_thread = new Thread(this);
|
||||
m_thread.start();
|
||||
}
|
||||
|
||||
/*
|
||||
* run() implementation.
|
||||
*/
|
||||
public void run ()
|
||||
{
|
||||
System.err.println("ReconfigureThread.run()- Running");
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Sleep an ammount equal the reconfigure interval for the Rpc
|
||||
try
|
||||
{
|
||||
m_thread.sleep(m_rpc.m_reconfigureInterval * 1000);
|
||||
}
|
||||
catch (InterruptedException e) { /* nothing to do */ }
|
||||
|
||||
// Re-configure the Rpc servlet.
|
||||
try
|
||||
{
|
||||
m_rpc.configureServlet();
|
||||
|
||||
// Check if it is no longer necessary to re-configure the servlet
|
||||
if (m_rpc.m_reconfigureInterval == 0)
|
||||
{
|
||||
System.err.println("ReconfigureTask.run()- Configuration changed to no longer perform timed re-configuration");
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("ReconfigureTask.run()- Exception caught during re-configure process, " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* stop() implementation.
|
||||
*/
|
||||
public void stop ()
|
||||
{
|
||||
m_thread.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public Rpc ()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/*
|
||||
* configureServlet() implementation.
|
||||
*/
|
||||
protected void configureServlet () throws Exception
|
||||
{
|
||||
// Read service configuration
|
||||
SvcConfig svcConfig = new SvcConfig(m_appFolderPath, m_configFolderPath);
|
||||
|
||||
// Get the reconfigure interval
|
||||
try
|
||||
{
|
||||
m_reconfigureInterval = Integer.parseInt(svcConfig.getSetting(SvcConfig.ReconfigureInterval));
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
System.err.println("Rpc.configureServlet()- Invalid reconfigure interval value format");
|
||||
m_reconfigureInterval = Integer.parseInt(SvcConfig.DefaultReconfigureIntervalValue);
|
||||
}
|
||||
|
||||
// Read enabled services configuration
|
||||
EnabledSvcsConfig enabledSvcsConfig = new EnabledSvcsConfig(m_configFolderPath);
|
||||
|
||||
// Create a map to keep track of the Rpc methods
|
||||
Map methodsMap = new HashMap();
|
||||
|
||||
// Instantiate the Rpc Methods
|
||||
RpcMethod getAuthPolicy = new GetAuthPolicy();
|
||||
getAuthPolicy.init(svcConfig, enabledSvcsConfig);
|
||||
methodsMap.put(getAuthPolicy.getId(), getAuthPolicy);
|
||||
|
||||
RpcMethod authenticate = new Authenticate();
|
||||
authenticate.init(svcConfig, enabledSvcsConfig);
|
||||
methodsMap.put(authenticate.getId(), authenticate);
|
||||
|
||||
RpcMethod getAuthToken = new GetAuthToken();
|
||||
getAuthToken.init(svcConfig, enabledSvcsConfig);
|
||||
methodsMap.put(getAuthToken.getId(), getAuthToken);
|
||||
|
||||
// Set the map as the methods map used by the servlet
|
||||
m_methodsMap = methodsMap;
|
||||
}
|
||||
|
||||
/*
|
||||
* init() implementation.
|
||||
*/
|
||||
public void init (ServletConfig config) throws ServletException
|
||||
{
|
||||
super.init(config);
|
||||
|
||||
System.err.println("Rpc.init()");
|
||||
|
||||
try
|
||||
{
|
||||
// Get the path to our configuration folder
|
||||
//
|
||||
// First check if it has been specified via a system property
|
||||
ServletContext context = config.getServletContext();
|
||||
m_appFolderPath = context.getRealPath(File.separator);
|
||||
m_configFolderPath = System.getProperty("com.novell.casa.authtoksvc.config");
|
||||
if (m_configFolderPath == null)
|
||||
{
|
||||
// The path to the svc config folder was not specified via a system
|
||||
// property, assume that it's location is off the WEB-INF folder for
|
||||
// our web application.
|
||||
m_configFolderPath = m_appFolderPath + "WEB-INF/conf";
|
||||
}
|
||||
|
||||
// Configure ourselves
|
||||
configureServlet();
|
||||
|
||||
// Check if we must start a thread to periodically reconfigure ourselves
|
||||
if (m_reconfigureInterval != 0)
|
||||
{
|
||||
m_reconfigureThread = new ReconfigureThread(this);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Rpc.init()- Exception caught: " + e.toString());
|
||||
throw new ServletException("Exception caught while instantiating Rpc methods");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* destroy() implementation.
|
||||
*/
|
||||
public void destroy ()
|
||||
{
|
||||
super.destroy();
|
||||
|
||||
System.err.println("Rpc.destroy()");
|
||||
|
||||
// Stop our re-configure thread
|
||||
if (m_reconfigureThread != null)
|
||||
{
|
||||
m_reconfigureThread.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* doGet() implementation.
|
||||
*/
|
||||
protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
doPost(request, response);
|
||||
}
|
||||
|
||||
/*
|
||||
* doPost() implementation.
|
||||
*/
|
||||
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
// Get ready to send back a reply
|
||||
response.setContentType("text/html");
|
||||
PrintWriter out = response.getWriter();
|
||||
|
||||
try
|
||||
{
|
||||
// Obtain the input stream and execute the requested method
|
||||
InputStream inStream = request.getInputStream();
|
||||
|
||||
String requestedMethod = request.getParameter("method");
|
||||
if (requestedMethod != null)
|
||||
{
|
||||
// Get the necessary method
|
||||
RpcMethod method = (RpcMethod) m_methodsMap.get(requestedMethod);
|
||||
if (method != null)
|
||||
{
|
||||
// Invoke the method to process the Rpc
|
||||
method.invoke(inStream, out);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unsupported method
|
||||
System.err.println("Rpc.doPost()- Unsupported method");
|
||||
response.sendError(response.SC_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Missing method parameter
|
||||
System.err.println("Rpc.doPost()- Missing method parameter");
|
||||
response.sendError(response.SC_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// tbd
|
||||
System.err.println("Rpc.doPost()- Exception caught: " + e.toString());
|
||||
response.sendError(response.SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
// Done sending out the reply
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/*
|
||||
* RpcMethod Interface.
|
||||
*
|
||||
* This is the interface implemented by Rpc Methods.
|
||||
*/
|
||||
public interface RpcMethod
|
||||
{
|
||||
/*
|
||||
* Initialize the Rpc method.
|
||||
*/
|
||||
void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception;
|
||||
|
||||
/*
|
||||
* Process Rpc.
|
||||
*/
|
||||
void invoke(InputStream inStream, PrintWriter out) throws IOException;
|
||||
|
||||
/*
|
||||
* Return the method id.
|
||||
*/
|
||||
String getId();
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
|
||||
/*
|
||||
* SessionToken class.
|
||||
*
|
||||
* This class constructs session tokens that Casa clients can present to
|
||||
* the Casa server to prove that an entity has been authenticated to
|
||||
* a particular realm. The format of the session token is as follows:
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <session_token>
|
||||
* <signature>signature value</signature>
|
||||
* <lifetime>lifetime value</lifetime>
|
||||
* <realm>realm value</realm>
|
||||
* <ident_id>identity id value</ident_id>
|
||||
* </session_token>
|
||||
*
|
||||
*/
|
||||
public class SessionToken
|
||||
{
|
||||
|
||||
private String m_id;
|
||||
private String m_realm;
|
||||
private String m_lifetime;
|
||||
private String m_signature;
|
||||
private String m_token;
|
||||
|
||||
/*
|
||||
* Class for handling parsing events.
|
||||
*/
|
||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
||||
{
|
||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
||||
private final static int AWAITING_ROOT_ELEMENT_END = 1;
|
||||
private final static int AWAITING_SIGNATURE_ELEMENT_START = 2;
|
||||
private final static int AWAITING_SIGNATURE_ELEMENT_END = 3;
|
||||
private final static int AWAITING_SIGNATURE_DATA = 4;
|
||||
private final static int AWAITING_LIFETIME_ELEMENT_START = 5;
|
||||
private final static int AWAITING_LIFETIME_ELEMENT_END = 6;
|
||||
private final static int AWAITING_LIFETIME_DATA = 7;
|
||||
private final static int AWAITING_REALM_ELEMENT_START = 8;
|
||||
private final static int AWAITING_REALM_ELEMENT_END = 9;
|
||||
private final static int AWAITING_REALM_DATA = 10;
|
||||
private final static int AWAITING_IDENT_ID_ELEMENT_START = 11;
|
||||
private final static int AWAITING_IDENT_ID_ELEMENT_END = 12;
|
||||
private final static int AWAITING_IDENT_ID_DATA = 13;
|
||||
private final static int DONE_PARSING = 14;
|
||||
|
||||
private SessionToken m_SessionToken;
|
||||
private int m_state;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SAXHandler (SessionToken SessionToken)
|
||||
{
|
||||
super();
|
||||
|
||||
// Initialize our members
|
||||
m_SessionToken = SessionToken;
|
||||
m_state = AWAITING_ROOT_ELEMENT_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* endDocument() implementation.
|
||||
*/
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
// Verify that we obtained all of the required elements
|
||||
if (m_state != DONE_PARSING)
|
||||
{
|
||||
System.err.println("SessionToken SAXHandler.endDocument()- Missing element");
|
||||
throw new SAXException("Missing element");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* startElement() implementation.
|
||||
*/
|
||||
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_ROOT_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.sessionTokenElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SIGNATURE_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SessionToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SIGNATURE_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.signatureElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SIGNATURE_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SessionToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_LIFETIME_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.lifetimeElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_LIFETIME_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SessionToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AWAITING_REALM_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.realmElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_REALM_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SessionToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_IDENT_ID_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.identIdElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_IDENT_ID_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SessionToken SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("SessionToken SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endElement() immplementation.
|
||||
*/
|
||||
public void endElement (String uri, String name, String qName) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_ROOT_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.sessionTokenElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = DONE_PARSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SessionToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SIGNATURE_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.signatureElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_LIFETIME_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SessionToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_LIFETIME_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.lifetimeElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_REALM_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SessionToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_REALM_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.realmElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_IDENT_ID_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SessionToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_IDENT_ID_ELEMENT_END:
|
||||
// Verify that we are processing the expected tag
|
||||
if (ProtoDefs.identIdElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_ROOT_ELEMENT_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SessionToken SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("SessionToken SAXHandler.startElement()- State error");
|
||||
throw new SAXException("State error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* character() implementation.
|
||||
*/
|
||||
public void characters (char ch[], int start, int length) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
|
||||
case AWAITING_SIGNATURE_DATA:
|
||||
// Consume the data
|
||||
m_SessionToken.m_signature = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SIGNATURE_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_LIFETIME_DATA:
|
||||
// Consume the data
|
||||
m_SessionToken.m_lifetime = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_LIFETIME_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_REALM_DATA:
|
||||
// Consume the data
|
||||
m_SessionToken.m_realm = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_REALM_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_IDENT_ID_DATA:
|
||||
// Consume the data
|
||||
m_SessionToken.m_id = new String(ch, start, length);
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_IDENT_ID_ELEMENT_END;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SessionToken(String id, String realm, String lifetime) throws Exception
|
||||
{
|
||||
// Save copies of the input parameters
|
||||
m_id = id;
|
||||
m_realm = realm;
|
||||
m_lifetime = lifetime;
|
||||
|
||||
// Generate a signature
|
||||
// tbd - Over id, realm, and lifetime data.
|
||||
m_signature = "tbd";
|
||||
|
||||
// Get a StringBuffer to help us with the construction of the token
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
// Start building the message
|
||||
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
|
||||
sb.append("<" + ProtoDefs.sessionTokenElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.signatureElementName + ">" + m_signature + "</" + ProtoDefs.signatureElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.lifetimeElementName + ">" + m_lifetime + "</" + ProtoDefs.lifetimeElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.realmElementName + ">" + m_realm + "</" + ProtoDefs.realmElementName + ">" + "\r\n");
|
||||
sb.append("<" + ProtoDefs.identIdElementName + ">" + m_id + "</" + ProtoDefs.identIdElementName + ">" + "\r\n");
|
||||
sb.append("</" + ProtoDefs.sessionTokenElementName + ">" + "\r\n");
|
||||
|
||||
// Save the token
|
||||
m_token = sb.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor given a session token string. The constructor
|
||||
* validates the token as part of its processing.
|
||||
*/
|
||||
public SessionToken(String token) throws Exception
|
||||
{
|
||||
// Decode the token string
|
||||
m_token = Base64Coder.decode(token);
|
||||
|
||||
// Now parse the token into its elements
|
||||
try
|
||||
{
|
||||
// Parse the SessionToken
|
||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
||||
SAXHandler handler = new SAXHandler(this);
|
||||
xr.setContentHandler(handler);
|
||||
xr.setErrorHandler(handler);
|
||||
|
||||
ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes());
|
||||
InputSource source = new InputSource(inStream);
|
||||
xr.parse(source);
|
||||
|
||||
// Verify the signature
|
||||
// tbd
|
||||
|
||||
// Verify that the token has not expired
|
||||
// tbd
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
System.err.println("SessionToken()- Parse exception: " + e.toString());
|
||||
throw new Exception("Protocol error");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string containing the session token.
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return Base64Coder.encode(m_token);
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to get the Identity Id
|
||||
*/
|
||||
public String getIdentId() throws Exception
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Method to get the Identity Repository Reference (Realm).
|
||||
*/
|
||||
public String getRealm() throws Exception
|
||||
{
|
||||
return m_realm;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.authtoksvc;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
* SvcConfig Class.
|
||||
*
|
||||
* This class obtains and maintains the service configuration.
|
||||
*
|
||||
*/
|
||||
public class SvcConfig
|
||||
{
|
||||
// Well known service configuration settings
|
||||
//
|
||||
// The LifetimeShorter value is the value by which token lifetime
|
||||
// values are shorten when specified to clients to make sure that
|
||||
// the clients detect token expirations before issuing the tokens
|
||||
// to a service for authentication purposes.
|
||||
public final static String SessionTokenLifetime = "SessionTokenLifetime";
|
||||
public final static String LifetimeShorter = "LifetimeShorter";
|
||||
public final static String IdentityAbstractionConfigFile = "IAConfigFile";
|
||||
public final static String StartSearchContext = "startSearchContext";
|
||||
public final static String ConfigFolderPath = "ConfigFolderPath";
|
||||
public final static String AppRootPath = "AppRootPath";
|
||||
public final static String ReconfigureInterval = "ReconfigureInterval";
|
||||
|
||||
// Default configuration values
|
||||
public final static String DefaultSessionTokenLifetimeValue = "43200"; // Seconds
|
||||
public final static String DefaultLifetimeShorterValue = "5"; // Seconds
|
||||
public final static String DefaultReconfigureIntervalValue = "60"; // Seconds
|
||||
|
||||
private static final String m_svcSettingsFileName = "svc.settings";
|
||||
private Map m_svcSettingsMap;
|
||||
|
||||
/*
|
||||
* Class for handling Authentication Request parsing events.
|
||||
*/
|
||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
||||
{
|
||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
||||
private final static int AWAITING_SETTING_ELEMENT_START = 1;
|
||||
private final static int AWAITING_SETTING_ELEMENT_DATA = 2;
|
||||
private final static int AWAITING_SETTING_ELEMENT_END = 3;
|
||||
private final static int DONE_PARSING = 4;
|
||||
|
||||
private final static String m_rootElementName = "settings";
|
||||
|
||||
private Map m_keyMap;
|
||||
private int m_state;
|
||||
private String m_currentKey;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public SAXHandler(Map keyMap)
|
||||
{
|
||||
super();
|
||||
|
||||
// Initialize our members
|
||||
m_keyMap = keyMap;
|
||||
m_state = AWAITING_ROOT_ELEMENT_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* endDocument() implementation.
|
||||
*/
|
||||
public void endDocument () throws SAXException
|
||||
{
|
||||
// Verify that we are not in an invalid state
|
||||
if (m_state != DONE_PARSING)
|
||||
{
|
||||
System.err.println("SvcConfig SAXHandler.endDocument()- Invalid state" + m_state);
|
||||
throw new SAXException("Invalid state at endDocument");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* startElement() implementation.
|
||||
*/
|
||||
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
case AWAITING_ROOT_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (m_rootElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SvcConfig SAXHandler.startElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SETTING_ELEMENT_START:
|
||||
// Keep track of the key name
|
||||
m_currentKey = qName;
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_DATA;
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("SvcConfig SAXHandler.startElement()- Invalid state " + m_state);
|
||||
throw new SAXException("Invalid state at startElement");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endElement() immplementation.
|
||||
*/
|
||||
public void endElement (String uri, String name, String qName) throws SAXException
|
||||
{
|
||||
// Proceed based on our state
|
||||
switch (m_state)
|
||||
{
|
||||
case AWAITING_SETTING_ELEMENT_DATA:
|
||||
case AWAITING_SETTING_ELEMENT_END:
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_START;
|
||||
break;
|
||||
|
||||
case AWAITING_SETTING_ELEMENT_START:
|
||||
// Verify that we are processing the expected tag
|
||||
if (m_rootElementName.equals(qName))
|
||||
{
|
||||
// Advance to the next state
|
||||
m_state = DONE_PARSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SvcConfig SAXHandler.endElement()- Un-expected element");
|
||||
throw new SAXException("Un-expected element");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("SvcConfig SAXHandler.endElement()- Invalid state " + m_state);
|
||||
throw new SAXException("Invalid state at endElement");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* character() implementation.
|
||||
*/
|
||||
public void characters (char ch[], int start, int length) throws SAXException
|
||||
{
|
||||
// Consume the data if in the right state
|
||||
if (m_state == AWAITING_SETTING_ELEMENT_DATA)
|
||||
{
|
||||
// Consume the data and add the key to map
|
||||
m_keyMap.put(m_currentKey, new String(ch, start, length));
|
||||
|
||||
// Advance to the next state
|
||||
m_state = AWAITING_SETTING_ELEMENT_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructor.
|
||||
*/
|
||||
public SvcConfig(String appRootPath, String svcConfigPath) throws Exception
|
||||
{
|
||||
System.err.println("SvcConfig()-");
|
||||
|
||||
System.err.println("SvcConfig()- SvcConfigPath = " + svcConfigPath);
|
||||
|
||||
// Create a map to keep track of the service settings
|
||||
m_svcSettingsMap = new HashMap();
|
||||
|
||||
try
|
||||
{
|
||||
// Get an input stream to services settings file
|
||||
File settingsFile = new File(svcConfigPath, m_svcSettingsFileName);
|
||||
FileInputStream inStream = new FileInputStream(settingsFile);
|
||||
|
||||
// Parse the file
|
||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
||||
SAXHandler handler = new SAXHandler(m_svcSettingsMap);
|
||||
xr.setContentHandler(handler);
|
||||
xr.setErrorHandler(handler);
|
||||
|
||||
InputSource source = new InputSource(inStream);
|
||||
xr.parse(source);
|
||||
inStream.close();
|
||||
|
||||
// Add the application and config folder path settings to our map
|
||||
m_svcSettingsMap.put(AppRootPath, appRootPath);
|
||||
m_svcSettingsMap.put(ConfigFolderPath, svcConfigPath);
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
System.err.println("SvcConfig()- Parse exception: " + e.toString());
|
||||
throw new Exception("SvcConfig()- svc.settings format error");
|
||||
}
|
||||
catch (SecurityException e)
|
||||
{
|
||||
System.err.println("SvcConfig()- SecurityException caught while accessing " + svcConfigPath + File.separator + m_svcSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
System.err.println("SvcConfig()- File " + svcConfigPath + File.separator + m_svcSettingsFileName + " not found");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println("SvcConfig()- IOException caught while trying to read " + svcConfigPath + File.separator + m_svcSettingsFileName + " Exception=" + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the value associated with the specified setting.
|
||||
*/
|
||||
public String getSetting(String settingName) throws Exception
|
||||
{
|
||||
// Try to find the setting in our map
|
||||
String value = (String) m_svcSettingsMap.get(settingName);
|
||||
if (value == null)
|
||||
{
|
||||
System.err.println("SvcConfig.getSetting()- Did not find setting " + settingName);
|
||||
|
||||
// The setting is not in our map, check if it is one to
|
||||
// which we have defaults.
|
||||
if (settingName.equals(SessionTokenLifetime) == true)
|
||||
{
|
||||
value = DefaultSessionTokenLifetimeValue;
|
||||
System.err.println("SvcConfig.getSetting()- Assigning default value " + value);
|
||||
|
||||
// Add the key to the map so that it can be found quicker next time
|
||||
m_svcSettingsMap.put(SessionTokenLifetime, DefaultSessionTokenLifetimeValue);
|
||||
}
|
||||
else if (settingName.equals(LifetimeShorter) == true)
|
||||
{
|
||||
value = DefaultLifetimeShorterValue;
|
||||
System.err.println("SvcConfig.getSetting()- Assigning default value " + value);
|
||||
|
||||
// Add the key to the map so that it can be found quicker next time
|
||||
m_svcSettingsMap.put(LifetimeShorter, DefaultLifetimeShorterValue);
|
||||
}
|
||||
else if (settingName.equals(ReconfigureInterval) == true)
|
||||
{
|
||||
value = DefaultReconfigureIntervalValue;
|
||||
System.err.println("SvcConfig.getSetting()- Assigning default value " + value);
|
||||
|
||||
// Add the key to the map so that it can be found quicker next time
|
||||
m_svcSettingsMap.put(ReconfigureInterval, DefaultReconfigureIntervalValue);
|
||||
}
|
||||
else if (settingName.equals(IdentityAbstractionConfigFile) == true)
|
||||
{
|
||||
System.err.println("SvcConfig.getSetting()- Mandatory setting " + IdentityAbstractionConfigFile + " not set");
|
||||
throw new Exception("Missing mandatory configuration setting");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("SvcConfig.getSetting()- Found setting " + settingName);
|
||||
System.err.println("SvcConfig.getSetting()- Setting value = " + value);
|
||||
|
||||
// Do some sanity checking
|
||||
// tbd - Make sure that the token lifetime values are greater than the LifetimeShorter
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
5
CASA-auth-token/server/AuthTokenSvc/svc.settings
Normal file
5
CASA-auth-token/server/AuthTokenSvc/svc.settings
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<settings>
|
||||
<IAConfigFile>Replace with path to the Identity Abstraction Realms Configuration File.</IAConfigFile>
|
||||
<SessionTokenLifetime>43200</SessionTokenLifetime>
|
||||
</settings>
|
||||
27
CASA-auth-token/server/AuthTokenSvc/web.xml
Normal file
27
CASA-auth-token/server/AuthTokenSvc/web.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
|
||||
<display-name>
|
||||
CasaAuthTokenSvc</display-name>
|
||||
<servlet>
|
||||
<description>
|
||||
The CasaAuthTokenSvc provides authentication tokens.
|
||||
</description>
|
||||
<display-name>
|
||||
Rpc</display-name>
|
||||
<servlet-name>Rpc</servlet-name>
|
||||
<servlet-class>
|
||||
com.novell.casa.authtoksvc.Rpc</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>Rpc</servlet-name>
|
||||
<url-pattern>/Rpc</url-pattern>
|
||||
</servlet-mapping>
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.html</welcome-file>
|
||||
<welcome-file>index.htm</welcome-file>
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
<welcome-file>default.html</welcome-file>
|
||||
<welcome-file>default.htm</welcome-file>
|
||||
<welcome-file>default.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
</web-app>
|
||||
37
CASA-auth-token/server/AuthTokenValidate/Makefile.am
Normal file
37
CASA-auth-token/server/AuthTokenValidate/Makefile.am
Normal 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) idenTokenProviders
|
||||
|
||||
DIST_SUBDIRS = linux idenTokenProviders
|
||||
|
||||
CFILES =
|
||||
|
||||
EXTRA_DIST = $(CFILES) *.h
|
||||
|
||||
.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
|
||||
|
||||
77
CASA-auth-token/server/AuthTokenValidate/README
Normal file
77
CASA-auth-token/server/AuthTokenValidate/README
Normal file
@@ -0,0 +1,77 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* README for libcasa_s_authtoken
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
libcasa_s_authtoken provides an API for the validation of CASA Authentication Tokens.
|
||||
The API provides a means for obtaining identity information about authenticated
|
||||
entities.
|
||||
|
||||
Applications should avoid calling directly into this library's APIs. Instead, applications
|
||||
should code to the PAM API to validate authentication credentials or allow an external
|
||||
module to perform the credential validation. To facilitate this, CASA Authentication
|
||||
provides PAM, Apache, and JAAS modules that can be used to validate credentials containing
|
||||
CASA Authentication tokens,
|
||||
|
||||
CONFIGURING TRUSTED AUTHENTICATION TOKEN SERVICES
|
||||
|
||||
tbd. Add info about the installation of public certificates and trusted certificate authorities.
|
||||
|
||||
CONFIGURING ADDITIONAL IDENTITY TOKEN PROVIDER MODULES
|
||||
|
||||
CASA Authentication Tokens contain Identity Tokens. The Identity Tokens contain the identity
|
||||
information about the entity being authenticated. Identity Tokens can be of different types,
|
||||
the type utilized for use with a particular service is configured at the time that the service
|
||||
is configured for CASA Authentication. The default identity token type is CasaIdentityToken.
|
||||
|
||||
libcasa_s_authtoken supports different identity token types through an API that allows for the
|
||||
configuration of different Identity Token Provider plug-ins. An Identity Token Provider plug-in
|
||||
is configured by placing a configuration file for the plug-ins in the
|
||||
/etc/opt/CASA/authtoken.d/modules.d folder. The name of the plug-in configuration file is related
|
||||
to the identity token type in the following manner: IdentityTokenTypeName.conf.
|
||||
|
||||
Identity Token Provider plug-in configuration files must must contain a directive indicating the
|
||||
path to the library implementing the Identity Token Provider plug-in (See the configuration file
|
||||
for the CasaIdentityToken plug-in for an example).
|
||||
|
||||
SERVER APPLICATION PROGRAMMING NOTES
|
||||
|
||||
The Validate CASA Authentication Token API is defined in casa_s_authtoken.h.
|
||||
|
||||
The API consists of a call to validate authentication tokens. The caller must supply a service
|
||||
name which must match the service name provided by the client when requesting the authentication
|
||||
token. Successful calls to the validate authentication token API will return a handle to a principal
|
||||
interface object. The principal interface object handle can be used to obtain identity information
|
||||
about the authenticated entity as well as information about the authentication realm. The principal
|
||||
interface object must be released after it is no longer needed. The amount and type of identity
|
||||
information associated with the principal interface is dependent on what is configured at the
|
||||
time that the service is enabled for CASA Authentication.
|
||||
|
||||
For examples of code which uses the Validate CASA Authentication Token API look at the implementations
|
||||
of the CASA Authentication PAM module and the CASA Authentication Provider Apache module.
|
||||
|
||||
IDENTITY TOKEN PROVIDER PROGRAMMING NOTES
|
||||
|
||||
The Identity Token Provider API is defined in iden_token_provider.h.
|
||||
|
||||
For an example see the implementation of the CASA Identity Token Provider.
|
||||
|
||||
SECURITY CONSIDERATIONS
|
||||
|
||||
CASA Authentication 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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
15
CASA-auth-token/server/AuthTokenValidate/TODO
Normal file
15
CASA-auth-token/server/AuthTokenValidate/TODO
Normal file
@@ -0,0 +1,15 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* TODO for libcasa_s_authtoken
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
This file contains a list of the items still outstanding for libcasa_s_authtoken.
|
||||
|
||||
OUTSTANDING ITEMS
|
||||
|
||||
- Change AuthTokens to be SOAP messages secured with WS-Security and WS-Trust.
|
||||
- Implement CheckAuthToken().
|
||||
- Finish README documentation.
|
||||
693
CASA-auth-token/server/AuthTokenValidate/authtoken.c
Normal file
693
CASA-auth-token/server/AuthTokenValidate/authtoken.c
Normal file
@@ -0,0 +1,693 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//
|
||||
// Parse states
|
||||
//
|
||||
#define AWAITING_ROOT_ELEMENT_START 0x0
|
||||
#define AWAITING_ROOT_ELEMENT_END 0x1
|
||||
#define AWAITING_SIGNATURE_DATA 0x2
|
||||
#define AWAITING_SIGNATURE_ELEMENT_START 0x3
|
||||
#define AWAITING_SIGNATURE_ELEMENT_END 0x4
|
||||
#define AWAITING_LIFETIME_DATA 0x5
|
||||
#define AWAITING_LIFETIME_ELEMENT_START 0x6
|
||||
#define AWAITING_LIFETIME_ELEMENT_END 0x7
|
||||
#define AWAITING_IDENT_TOKEN_ELEMENT_START 0x8
|
||||
#define AWAITING_IDENT_TOKEN_ELEMENT_END 0x9
|
||||
#define AWAITING_IDENT_TOKEN_DATA 0xA
|
||||
#define AWAITING_TYPE_ELEMENT_START 0xB
|
||||
#define AWAITING_TYPE_ELEMENT_END 0xC
|
||||
#define AWAITING_TYPE_DATA 0xD
|
||||
#define DONE_PARSING 0xE
|
||||
|
||||
//
|
||||
// Authentication Token Parse Structure
|
||||
//
|
||||
typedef struct _AuthTokenParse
|
||||
{
|
||||
XML_Parser p;
|
||||
int state;
|
||||
int elementDataProcessed;
|
||||
AuthToken *pAuthToken;
|
||||
CasaStatus status;
|
||||
|
||||
} AuthTokenParse, *PAuthTokenParse;
|
||||
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
void XMLCALL
|
||||
AuthTokenStartElementHandler(
|
||||
IN void *pUserData,
|
||||
IN const XML_Char *name,
|
||||
IN const XML_Char **atts)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
AuthTokenParse *pAuthTokenParse = (AuthTokenParse*) pUserData;
|
||||
|
||||
DbgTrace(2, "-AuthTokenStartElementHandler- Start\n", 0);
|
||||
|
||||
// Proceed based on the state
|
||||
switch (pAuthTokenParse->state)
|
||||
{
|
||||
case AWAITING_ROOT_ELEMENT_START:
|
||||
|
||||
// In this state, we are only expecting the Authentication
|
||||
// Response Element.
|
||||
if (strcmp(name, AUTH_TOKEN_ELEMENT_NAME) == 0)
|
||||
{
|
||||
// Good, advance to the next state.
|
||||
pAuthTokenParse->state = AWAITING_SIGNATURE_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected start element\n", 0);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SIGNATURE_ELEMENT_START:
|
||||
|
||||
// In this state, we are only expecting the Signature Element.
|
||||
if (strcmp(name, SIGNATURE_ELEMENT_NAME) == 0)
|
||||
{
|
||||
// Good, advance to the next state.
|
||||
pAuthTokenParse->state = AWAITING_SIGNATURE_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected start element\n", 0);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_LIFETIME_ELEMENT_START:
|
||||
|
||||
// In this state, we are only expecting the Lifetime Element.
|
||||
if (strcmp(name, LIFETIME_ELEMENT_NAME) == 0)
|
||||
{
|
||||
// Good, advance to the next state.
|
||||
pAuthTokenParse->state = AWAITING_LIFETIME_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected start element\n", 0);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_IDENT_TOKEN_ELEMENT_START:
|
||||
|
||||
// In this state, we are only expecting the Identity Token Element.
|
||||
if (strcmp(name, IDENTITY_TOKEN_ELEMENT_NAME) == 0)
|
||||
{
|
||||
// Good, advance to the next state.
|
||||
pAuthTokenParse->state = AWAITING_TYPE_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected start element\n", 0);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_TYPE_ELEMENT_START:
|
||||
|
||||
// In this state, we are only expecting the Type Element.
|
||||
if (strcmp(name, TYPE_ELEMENT_NAME) == 0)
|
||||
{
|
||||
// Good, advance to the next state.
|
||||
pAuthTokenParse->state = AWAITING_TYPE_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected start element\n", 0);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DbgTrace(0, "-AuthTokenStartElementHandler- Un-expected state = %d\n", pAuthTokenParse->state);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
DbgTrace(2, "-AuthTokenStartElementHandler- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
CasaStatus
|
||||
ConsumeElementData(
|
||||
IN AuthTokenParse *pAuthTokenParse,
|
||||
IN const XML_Char *s,
|
||||
IN int len,
|
||||
INOUT char **ppElementData,
|
||||
INOUT int *pElementDataLen)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus = CASA_STATUS_SUCCESS;
|
||||
|
||||
DbgTrace(3, "-ConsumeElementData- Start\n", 0);
|
||||
|
||||
// Proceed based on whether or not we have already consumed data
|
||||
// for this element.
|
||||
if (*ppElementData == NULL)
|
||||
{
|
||||
// We have not yet consumed data for this element
|
||||
pAuthTokenParse->elementDataProcessed = len;
|
||||
|
||||
// Allocate a buffer to hold this element data (null terminated).
|
||||
*ppElementData = (char*) malloc(len + 1);
|
||||
if (*ppElementData)
|
||||
{
|
||||
memset(*ppElementData, 0, len + 1);
|
||||
memcpy(*ppElementData, s, len);
|
||||
|
||||
// Return the length of the element data buffer
|
||||
*pElementDataLen = pAuthTokenParse->elementDataProcessed + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *pNewBuf;
|
||||
|
||||
// We have already received token data, append this data to it.
|
||||
pNewBuf = (char*) malloc(pAuthTokenParse->elementDataProcessed + len + 1);
|
||||
if (pNewBuf)
|
||||
{
|
||||
memset(pNewBuf,
|
||||
0,
|
||||
pAuthTokenParse->elementDataProcessed + len + 1);
|
||||
memcpy(pNewBuf,
|
||||
*ppElementData,
|
||||
pAuthTokenParse->elementDataProcessed);
|
||||
memcpy(pNewBuf + pAuthTokenParse->elementDataProcessed, s, len);
|
||||
pAuthTokenParse->elementDataProcessed += len;
|
||||
|
||||
// Swap the buffers
|
||||
free(*ppElementData);
|
||||
*ppElementData = pNewBuf;
|
||||
|
||||
// Return the length of the element data buffer
|
||||
*pElementDataLen = pAuthTokenParse->elementDataProcessed + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
}
|
||||
|
||||
DbgTrace(3, "-ConsumeElementData- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
void XMLCALL
|
||||
AuthTokenCharDataHandler(
|
||||
IN void *pUserData,
|
||||
IN const XML_Char *s,
|
||||
IN int len)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
AuthTokenParse *pAuthTokenParse = (AuthTokenParse*) pUserData;
|
||||
|
||||
DbgTrace(2, "-AuthTokenCharDataHandler- Start\n", 0);
|
||||
|
||||
// Just exit if being called to process LF and CR characters
|
||||
if (len == 1
|
||||
&& ((*s == '\n') || (*s == '\r')))
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Proceed based on the state
|
||||
switch (pAuthTokenParse->state)
|
||||
{
|
||||
case AWAITING_SIGNATURE_DATA:
|
||||
case AWAITING_SIGNATURE_ELEMENT_END:
|
||||
|
||||
pAuthTokenParse->status = ConsumeElementData(pAuthTokenParse,
|
||||
s,
|
||||
len,
|
||||
&pAuthTokenParse->pAuthToken->pSignature,
|
||||
&pAuthTokenParse->pAuthToken->signatureLen);
|
||||
if (CASA_SUCCESS(pAuthTokenParse->status))
|
||||
{
|
||||
// Advanced to the next state
|
||||
pAuthTokenParse->state = AWAITING_SIGNATURE_ELEMENT_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_LIFETIME_DATA:
|
||||
case AWAITING_LIFETIME_ELEMENT_END:
|
||||
|
||||
// Convert the lifetime string to a numeric value
|
||||
pAuthTokenParse->pAuthToken->tokenLifetime = dtoul((char*) s, len);
|
||||
|
||||
// Advanced to the next state
|
||||
pAuthTokenParse->state = AWAITING_LIFETIME_ELEMENT_END;
|
||||
break;
|
||||
|
||||
case AWAITING_TYPE_DATA:
|
||||
case AWAITING_TYPE_ELEMENT_END:
|
||||
|
||||
pAuthTokenParse->status = ConsumeElementData(pAuthTokenParse,
|
||||
s,
|
||||
len,
|
||||
&pAuthTokenParse->pAuthToken->pIdenTokenType,
|
||||
&pAuthTokenParse->pAuthToken->idenTokenTypeLen);
|
||||
if (CASA_SUCCESS(pAuthTokenParse->status))
|
||||
{
|
||||
// Advanced to the next state
|
||||
pAuthTokenParse->state = AWAITING_TYPE_ELEMENT_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_IDENT_TOKEN_DATA:
|
||||
case AWAITING_IDENT_TOKEN_ELEMENT_END:
|
||||
|
||||
pAuthTokenParse->status = ConsumeElementData(pAuthTokenParse,
|
||||
s,
|
||||
len,
|
||||
&pAuthTokenParse->pAuthToken->pIdenToken,
|
||||
&pAuthTokenParse->pAuthToken->idenTokenLen);
|
||||
if (CASA_SUCCESS(pAuthTokenParse->status))
|
||||
{
|
||||
// Advanced to the next state
|
||||
pAuthTokenParse->state = AWAITING_IDENT_TOKEN_ELEMENT_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DbgTrace(0, "-AuthTokenCharDataHandler- Un-expected state = %d\n", pAuthTokenParse->state);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
DbgTrace(2, "-AuthTokenCharDataHandler- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
void XMLCALL
|
||||
AuthTokenEndElementHandler(
|
||||
IN void *pUserData,
|
||||
IN const XML_Char *name)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
AuthTokenParse *pAuthTokenParse = (AuthTokenParse*) pUserData;
|
||||
|
||||
DbgTrace(2, "-AuthTokenEndElementHandler- Start\n", 0);
|
||||
|
||||
// Proceed based on the state
|
||||
switch (pAuthTokenParse->state)
|
||||
{
|
||||
case AWAITING_ROOT_ELEMENT_END:
|
||||
|
||||
// In this state, we are only expecting the Authentication
|
||||
// Token Element.
|
||||
if (strcmp(name, AUTH_TOKEN_ELEMENT_NAME) == 0)
|
||||
{
|
||||
// Done.
|
||||
pAuthTokenParse->state = DONE_PARSING;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-AuthTokenEndHandler- Un-expected end element\n", 0);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_SIGNATURE_ELEMENT_END:
|
||||
|
||||
// In this state, we are only expecting the Signature Element.
|
||||
if (strcmp(name, SIGNATURE_ELEMENT_NAME) == 0)
|
||||
{
|
||||
// Good, advance to the next state.
|
||||
pAuthTokenParse->state = AWAITING_LIFETIME_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-AuthTokenEndElementHandler- Un-expected end element\n", 0);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_LIFETIME_ELEMENT_END:
|
||||
|
||||
// In this state, we are only expecting the Lifetime Element.
|
||||
if (strcmp(name, LIFETIME_ELEMENT_NAME) == 0)
|
||||
{
|
||||
// Good, advance to the next state.
|
||||
pAuthTokenParse->state = AWAITING_IDENT_TOKEN_ELEMENT_START;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-AuthTokenEndElementHandler- Un-expected end element\n", 0);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_TYPE_ELEMENT_END:
|
||||
|
||||
// In this state, we are only expecting the Type Element.
|
||||
if (strcmp(name, TYPE_ELEMENT_NAME) == 0)
|
||||
{
|
||||
// Good, advance to the next state.
|
||||
pAuthTokenParse->state = AWAITING_IDENT_TOKEN_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-AuthTokenEndElementHandler- Un-expected end element\n", 0);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case AWAITING_IDENT_TOKEN_ELEMENT_END:
|
||||
|
||||
// In this state, we are only expecting the Identity Token Element.
|
||||
if (strcmp(name, IDENTITY_TOKEN_ELEMENT_NAME) == 0)
|
||||
{
|
||||
// Good, advance to the next state.
|
||||
pAuthTokenParse->state = AWAITING_ROOT_ELEMENT_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-AuthTokenEndElementHandler- Un-expected end element\n", 0);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DbgTrace(0, "-AuthTokenEndElementHandler- Un-expected state = %d\n", pAuthTokenParse->state);
|
||||
XML_StopParser(pAuthTokenParse->p, XML_FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
DbgTrace(2, "-AuthTokenEndElementHandler- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
CreateAuthToken(
|
||||
IN char *pTokenBuf,
|
||||
IN int tokenBufLen,
|
||||
INOUT AuthToken **ppAuthToken)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus = CASA_STATUS_SUCCESS;
|
||||
AuthTokenParse authTokenParse = {0};
|
||||
AuthToken *pAuthToken;
|
||||
|
||||
DbgTrace(1, "-CreateAuthToken- Start\n", 0);
|
||||
|
||||
/*
|
||||
* Authentication tokens have the following format:
|
||||
*
|
||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
* <auth_token>
|
||||
* <signature>signature value</signature>
|
||||
* <lifetime>lifetime value</lifetime>
|
||||
* <ident_token><type>identity token type</type>identity token data</ident_token>
|
||||
* </auth_token>
|
||||
*
|
||||
*/
|
||||
|
||||
// Allocate AuthToken object
|
||||
pAuthToken = malloc(sizeof(*pAuthToken));
|
||||
if (pAuthToken)
|
||||
{
|
||||
XML_Parser p;
|
||||
|
||||
// Initialize the AuthToken object and set it in the
|
||||
// authentication response parse object.
|
||||
memset(pAuthToken, 0, sizeof(*pAuthToken));
|
||||
authTokenParse.pAuthToken = pAuthToken;
|
||||
|
||||
// Create parser
|
||||
p = XML_ParserCreate(NULL);
|
||||
if (p)
|
||||
{
|
||||
// Keep track of the parser in our parse object
|
||||
authTokenParse.p = p;
|
||||
|
||||
// Initialize the status within the parse object
|
||||
authTokenParse.status = CASA_STATUS_SUCCESS;
|
||||
|
||||
// Set the start and end element handlers
|
||||
XML_SetElementHandler(p,
|
||||
AuthTokenStartElementHandler,
|
||||
AuthTokenEndElementHandler);
|
||||
|
||||
// Set the character data handler
|
||||
XML_SetCharacterDataHandler(p, AuthTokenCharDataHandler);
|
||||
|
||||
|
||||
// Set our user data
|
||||
XML_SetUserData(p, &authTokenParse);
|
||||
|
||||
// Parse the document
|
||||
if (XML_Parse(p, pTokenBuf, tokenBufLen, 1) == XML_STATUS_OK)
|
||||
{
|
||||
// Verify that the parse operation completed successfully
|
||||
if (authTokenParse.state == DONE_PARSING)
|
||||
{
|
||||
// The parse operation succeded.
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-CreateAuthToken- Parse operation did not complete\n", 0);
|
||||
|
||||
// Check if a status has been recorded
|
||||
if (authTokenParse.status != CASA_STATUS_SUCCESS)
|
||||
{
|
||||
retStatus = authTokenParse.status;
|
||||
}
|
||||
else
|
||||
{
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_PROTOCOL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-CreateAuthToken- Parse error %d\n", XML_GetErrorCode(p));
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_PROTOCOL_ERROR);
|
||||
}
|
||||
|
||||
// Free the parser
|
||||
XML_ParserFree(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-CreateAuthToken- Parser creation error\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
// Return the AuthenticationResp object to the caller if necessary
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
*ppAuthToken = pAuthToken;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(pAuthToken);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-CreateAuthToken- Memory allocation error\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
DbgTrace(1, "-CreateAuthToken- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
RelAuthToken(
|
||||
IN AuthToken *pAuthToken)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
DbgTrace(1, "-RelAuthToken- Start\n", 0);
|
||||
|
||||
// Free the resources associated with the object
|
||||
if (pAuthToken->pSignature)
|
||||
free(pAuthToken->pSignature);
|
||||
|
||||
if (pAuthToken->pIdenTokenType)
|
||||
free(pAuthToken->pIdenTokenType);
|
||||
|
||||
if (pAuthToken->pIdenToken)
|
||||
free(pAuthToken->pIdenToken);
|
||||
|
||||
free(pAuthToken);
|
||||
|
||||
DbgTrace(1, "-RelAuthToken- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
CheckAuthToken(
|
||||
IN AuthToken *pAuthToken,
|
||||
IN const char *pServiceName)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L0
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus = CASA_STATUS_SUCCESS;
|
||||
|
||||
DbgTrace(1, "-CheckuthToken- Start\n", 0);
|
||||
|
||||
// tbd
|
||||
|
||||
DbgTrace(1, "-CheckAuthToken- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
764
CASA-auth-token/server/AuthTokenValidate/config.c
Normal file
764
CASA-auth-token/server/AuthTokenValidate/config.c
Normal file
@@ -0,0 +1,764 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//
|
||||
// Config Key object
|
||||
//
|
||||
typedef struct _ConfigKey
|
||||
{
|
||||
LIST_ENTRY listEntry;
|
||||
char *pKeyName;
|
||||
int keyNameLen;
|
||||
char *pValue;
|
||||
int valueLen;
|
||||
|
||||
} ConfigKey, *pConfigKey;
|
||||
|
||||
//
|
||||
// Config Interface instance data
|
||||
//
|
||||
typedef struct _ConfigIfInstance
|
||||
{
|
||||
LIST_ENTRY listEntry;
|
||||
int refCount;
|
||||
char *pConfigFolder;
|
||||
int configFolderLen;
|
||||
char *pConfigName;
|
||||
int configNameLen;
|
||||
LIST_ENTRY configKeyListHead;
|
||||
ConfigIf configIf;
|
||||
|
||||
} ConfigIfInstance, *PConfigIfInstance;
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
// ConfigIf variables
|
||||
static
|
||||
LIST_ENTRY g_configIfListHead = {&g_configIfListHead, &g_configIfListHead};
|
||||
|
||||
static
|
||||
int g_numConfigIfObjs = 0;
|
||||
|
||||
// Synchronization mutex
|
||||
static
|
||||
HANDLE g_configIfMutex = NULL;
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
void
|
||||
RemoveWhiteSpaceFromTheEnd(
|
||||
IN const char *pInString)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
char *pLineEnd = (char*) pInString + strlen(pInString) - 1;
|
||||
|
||||
|
||||
DbgTrace(3, "-RemoveWhiteSpaceFromTheEnd- Start\n", 0);
|
||||
|
||||
while (pLineEnd != pInString)
|
||||
{
|
||||
if (*pLineEnd == '\n'
|
||||
|| *pLineEnd == ' '
|
||||
|| *pLineEnd == '\t')
|
||||
{
|
||||
// Strike this character
|
||||
*pLineEnd = '\0';
|
||||
pLineEnd --;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found a non-white character
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DbgTrace(3, "-RemoveWhiteSpaceFromTheEnd- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
char*
|
||||
SkipWhiteSpace(
|
||||
IN const char *pInString)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
char *pOutString = (char*) pInString;
|
||||
|
||||
DbgTrace(3, "-SkipWhiteSpace- Start\n", 0);
|
||||
|
||||
while (*pOutString != '\0')
|
||||
{
|
||||
if (*pOutString == '\n'
|
||||
|| *pOutString == ' '
|
||||
|| *pOutString == '\t')
|
||||
{
|
||||
// Skip this character
|
||||
pOutString ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found a non-white character
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DbgTrace(3, "-SkipWhiteSpace- End\n", 0);
|
||||
|
||||
return pOutString;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
char*
|
||||
SkipNonWhiteSpace(
|
||||
IN const char *pInString)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
char *pOutString = (char*) pInString;
|
||||
|
||||
DbgTrace(3, "-SkipNonWhiteSpace- Start\n", 0);
|
||||
|
||||
while (*pOutString != '\0')
|
||||
{
|
||||
if (*pOutString == '\n'
|
||||
|| *pOutString == ' '
|
||||
|| *pOutString == '\t')
|
||||
{
|
||||
// Found a white character
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip this character
|
||||
pOutString ++;
|
||||
}
|
||||
}
|
||||
|
||||
DbgTrace(3, "-SkipNonWhiteSpace- End\n", 0);
|
||||
|
||||
return pOutString;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
void
|
||||
LowerCaseString(
|
||||
IN char *pDestString,
|
||||
IN const char *pSrcString)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
int i;
|
||||
|
||||
DbgTrace(3, "-LowerCaseString- Start\n", 0);
|
||||
|
||||
// Copy the string as lower case
|
||||
for (i = 0; pSrcString[i] != '\0'; i++)
|
||||
{
|
||||
if (isalpha(pSrcString[i]))
|
||||
pDestString[i] = tolower(pSrcString[i]);
|
||||
else
|
||||
pDestString[i] = pSrcString[i];
|
||||
}
|
||||
|
||||
// Null terminate the destination string
|
||||
pDestString[i] = '\0';
|
||||
|
||||
DbgTrace(3, "-LowerCaseString- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
int SSCS_CALL
|
||||
AddReference(
|
||||
IN const void *pIfInstance)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Interface reference count.
|
||||
//
|
||||
// Description:
|
||||
// Increases interface reference count.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
int refCount;
|
||||
ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf);
|
||||
|
||||
DbgTrace(2, "-AddReference- Start\n", 0);
|
||||
|
||||
// Increment the reference count on the object
|
||||
PlatAcquireMutex(g_configIfMutex);
|
||||
pConfigIfInstance->refCount ++;
|
||||
refCount = pConfigIfInstance->refCount;
|
||||
PlatReleaseMutex(g_configIfMutex);
|
||||
|
||||
DbgTrace(2, "-AddReference- End, refCount = %08X\n", refCount);
|
||||
|
||||
return refCount;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
void SSCS_CALL
|
||||
ReleaseReference(
|
||||
IN const void *pIfInstance)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Nothing.
|
||||
//
|
||||
// Description:
|
||||
// Decreases interface reference count. The interface is deallocated if
|
||||
// the reference count becomes zero.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
bool freeObj = false;
|
||||
ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf);
|
||||
|
||||
DbgTrace(2, "-ReleaseReference- Start\n", 0);
|
||||
|
||||
// Decrement the reference count on the object and determine if it needs to
|
||||
// be released.
|
||||
PlatAcquireMutex(g_configIfMutex);
|
||||
pConfigIfInstance->refCount --;
|
||||
if (pConfigIfInstance->refCount == 0)
|
||||
{
|
||||
// The object needs to be released, forget about it.
|
||||
freeObj = true;
|
||||
g_numConfigIfObjs --;
|
||||
RemoveEntryList(&pConfigIfInstance->listEntry);
|
||||
}
|
||||
PlatReleaseMutex(g_configIfMutex);
|
||||
|
||||
// Free object if necessary
|
||||
if (freeObj)
|
||||
{
|
||||
// Free all of the config key objects associated with this configuration
|
||||
// interface instance.
|
||||
while (!IsListEmpty(&pConfigIfInstance->configKeyListHead))
|
||||
{
|
||||
LIST_ENTRY *pListEntry;
|
||||
ConfigKey *pConfigKey;
|
||||
|
||||
// Get reference to entry at the head of the list
|
||||
pListEntry = pConfigIfInstance->configKeyListHead.Flink;
|
||||
pConfigKey = CONTAINING_RECORD(pListEntry, ConfigKey, listEntry);
|
||||
|
||||
// Free the buffers associated with the ConfigKey
|
||||
free(pConfigKey->pKeyName);
|
||||
free(pConfigKey->pValue);
|
||||
|
||||
// Remove the entry from the list
|
||||
RemoveEntryList(&pConfigKey->listEntry);
|
||||
|
||||
// Finish freeing the ConfigKey
|
||||
free(pConfigKey);
|
||||
}
|
||||
|
||||
// Free the rest of the buffers associated with the interface instance data
|
||||
free(pConfigIfInstance->pConfigFolder);
|
||||
free(pConfigIfInstance->pConfigName);
|
||||
free(pConfigIfInstance);
|
||||
}
|
||||
|
||||
DbgTrace(2, "-ReleaseReference- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
char* SSCS_CALL
|
||||
GetEntryValue(
|
||||
IN const void *pIfInstance,
|
||||
IN const char *pKeyName)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pKeyName -
|
||||
// Pointer to NULL terminated string that contains the
|
||||
// name of the key whose value is being requested.
|
||||
//
|
||||
// Returns:
|
||||
// Pointer to NULL terminated string with value being requested or NULL.
|
||||
//
|
||||
// Description:
|
||||
// Gets value associated with a key for the configuration object.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf);
|
||||
char *pValue = NULL;
|
||||
LIST_ENTRY *pListEntry;
|
||||
ConfigKey *pConfigKey;
|
||||
int keyNameLen = strlen(pKeyName);
|
||||
char *pKeyNameLowercase;
|
||||
|
||||
DbgTrace(2, "-GetEntryValue- Start\n", 0);
|
||||
|
||||
// Allocate enough space to hold lower case version of the key name
|
||||
pKeyNameLowercase = malloc(keyNameLen + 1);
|
||||
if (pKeyNameLowercase)
|
||||
{
|
||||
// Lower case the key name
|
||||
LowerCaseString(pKeyNameLowercase, pKeyName);
|
||||
|
||||
// Try to find matching ConfigKey
|
||||
pListEntry = pConfigIfInstance->configKeyListHead.Flink;
|
||||
while (pListEntry != &pConfigIfInstance->configKeyListHead)
|
||||
{
|
||||
// Get pointer to the current entry
|
||||
pConfigKey = CONTAINING_RECORD(pListEntry, ConfigKey, listEntry);
|
||||
|
||||
// Check if we have a match
|
||||
if (pConfigKey->keyNameLen == keyNameLen
|
||||
&& memcmp(pKeyNameLowercase, pConfigKey->pKeyName, keyNameLen) == 0)
|
||||
{
|
||||
// We found it, return its value.
|
||||
pValue = malloc(pConfigKey->valueLen + 1);
|
||||
if (pValue)
|
||||
{
|
||||
strcpy(pValue, pConfigKey->pValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetEntryValue- Buffer allocation failure\n", 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Advance to the next entry
|
||||
pListEntry = pListEntry->Flink;
|
||||
}
|
||||
|
||||
// Free the lower case version of the key name
|
||||
free(pKeyNameLowercase);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetEntryValue- Buffer allocation failure\n", 0);
|
||||
}
|
||||
|
||||
DbgTrace(2, "-GetEntryValue- End, pValue = %08X\n", (unsigned int) pValue);
|
||||
|
||||
return pValue;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
GetConfigInterface(
|
||||
IN const char *pConfigFolder,
|
||||
IN const char *pConfigName,
|
||||
INOUT ConfigIf **ppConfigIf)
|
||||
//
|
||||
// Arguments:
|
||||
// pConfigFolder -
|
||||
// Pointer to NULL terminated string that contains the name of
|
||||
// the folder containing the configuration file.
|
||||
//
|
||||
// pConfigName -
|
||||
// Pointer to NULL terminated string containing the name of the
|
||||
// configuration entry.
|
||||
//
|
||||
// ppConfigIf -
|
||||
// Pointer to variable that will receive pointer to ConfigIf
|
||||
// instance.
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Get configuration interface to specified configuration entry.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
int configFolderLen = strlen(pConfigFolder);
|
||||
int configNameLen = strlen(pConfigName);
|
||||
ConfigIfInstance *pConfigIfInstance;
|
||||
LIST_ENTRY *pListEntry;
|
||||
CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_OBJECT_NOT_FOUND);
|
||||
|
||||
DbgTrace(2, "-GetConfigInterface- Start\n", 0);
|
||||
|
||||
PlatAcquireMutex(g_configIfMutex);
|
||||
|
||||
// Check if we already have an entry in our list for the configuration
|
||||
pListEntry = g_configIfListHead.Flink;
|
||||
while (pListEntry != &g_configIfListHead)
|
||||
{
|
||||
// Get pointer to the current entry
|
||||
pConfigIfInstance = CONTAINING_RECORD(pListEntry, ConfigIfInstance, listEntry);
|
||||
|
||||
// Check if we have a match
|
||||
if (pConfigIfInstance->configFolderLen == configFolderLen
|
||||
&& pConfigIfInstance->configNameLen == configNameLen
|
||||
&& memcmp(pConfigFolder, pConfigIfInstance->pConfigFolder, configFolderLen) == 0
|
||||
&& memcmp(pConfigName, pConfigIfInstance->pConfigName, configNameLen) == 0)
|
||||
{
|
||||
// We found it, return the ConfigIf associated with the instance data
|
||||
// after incrementing its reference count.
|
||||
pConfigIfInstance->refCount ++;
|
||||
*ppConfigIf = &pConfigIfInstance->configIf;
|
||||
|
||||
// Success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
// Advance to the next entry
|
||||
pListEntry = pListEntry->Flink;
|
||||
}
|
||||
|
||||
// Proceed to create interface instance data for the configuration if none was found
|
||||
if (retStatus != CASA_STATUS_SUCCESS)
|
||||
{
|
||||
char *pFilePath;
|
||||
|
||||
// Build a string containing the configuration file path
|
||||
pFilePath = malloc(configFolderLen + 1 + configNameLen + sizeof(".conf"));
|
||||
if (pFilePath)
|
||||
{
|
||||
FILE *pConfigFile;
|
||||
|
||||
strcpy(pFilePath, pConfigFolder);
|
||||
strcat(pFilePath, "/");
|
||||
strcat(pFilePath, pConfigName);
|
||||
strcat(pFilePath, ".conf");
|
||||
|
||||
// Open the configuration file for reading
|
||||
pConfigFile = fopen(pFilePath, "r");
|
||||
if (pConfigFile)
|
||||
{
|
||||
// Opened the file, create a ConfigIfInstance object for it.
|
||||
pConfigIfInstance = malloc(sizeof(*pConfigIfInstance));
|
||||
if (pConfigIfInstance)
|
||||
{
|
||||
// Initialize the list head within the instance data
|
||||
InitializeListHead(&pConfigIfInstance->configKeyListHead);
|
||||
|
||||
// Initialize the ConfigIf within the instance data
|
||||
pConfigIfInstance->configIf.addReference = AddReference;
|
||||
pConfigIfInstance->configIf.releaseReference = ReleaseReference;
|
||||
pConfigIfInstance->configIf.getEntryValue = GetEntryValue;
|
||||
|
||||
// Save the ConfigFolder and ConfigName information within the instance data
|
||||
pConfigIfInstance->pConfigFolder = malloc(configFolderLen + 1);
|
||||
if (pConfigIfInstance->pConfigFolder)
|
||||
{
|
||||
strcpy(pConfigIfInstance->pConfigFolder, pConfigFolder);
|
||||
pConfigIfInstance->configFolderLen = configFolderLen;
|
||||
|
||||
pConfigIfInstance->pConfigName = malloc(configNameLen + 1);
|
||||
if (pConfigIfInstance->pConfigName)
|
||||
{
|
||||
strcpy(pConfigIfInstance->pConfigName, pConfigName);
|
||||
pConfigIfInstance->configNameLen = configNameLen;
|
||||
|
||||
// Add the instance data into our list and bump up its reference count
|
||||
// since we did that.
|
||||
InsertTailList(&g_configIfListHead, &pConfigIfInstance->listEntry);
|
||||
pConfigIfInstance->refCount = 1;
|
||||
|
||||
// At this point we want to return success to the caller even if we
|
||||
// experience a read error.
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
|
||||
// Return the ConfigIf associated with the instance data after
|
||||
// incrementing its reference count.
|
||||
pConfigIfInstance->refCount ++;
|
||||
*ppConfigIf = &pConfigIfInstance->configIf;
|
||||
|
||||
// Now update the instance data with the information present in the file
|
||||
if (fseek(pConfigFile, 0, SEEK_SET) == 0)
|
||||
{
|
||||
char line[512];
|
||||
|
||||
while (fgets(line, sizeof(line), pConfigFile) != NULL)
|
||||
{
|
||||
int lineLength;
|
||||
|
||||
RemoveWhiteSpaceFromTheEnd(line);
|
||||
|
||||
lineLength = strlen(line);
|
||||
if (lineLength != 0)
|
||||
{
|
||||
char *pKey;
|
||||
char *pKeyEnd;
|
||||
char *pValue;
|
||||
ConfigKey *pConfigKey;
|
||||
|
||||
// Attempt to find the key
|
||||
pKey = SkipWhiteSpace(line);
|
||||
|
||||
// Make sure that we are not dealing with an empty line or a comment
|
||||
if (*pKey == '\0' || *pKey == '#')
|
||||
continue;
|
||||
|
||||
// Go past the key
|
||||
pKeyEnd = SkipNonWhiteSpace(pKey);
|
||||
|
||||
// Protect against a malformed line
|
||||
if (*pKeyEnd == '\0')
|
||||
{
|
||||
DbgTrace(0, "-GetConfigInterface- Key found without value\n", 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Attempt to find the value
|
||||
pValue = SkipWhiteSpace(pKeyEnd);
|
||||
|
||||
// Protect against a malformed line
|
||||
if (*pValue == '\0')
|
||||
{
|
||||
DbgTrace(0, "-GetConfigInterface- Key found without value\n", 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Delineate the key
|
||||
*pKeyEnd = '\0';
|
||||
|
||||
// Create a ConfigKey object for this key/value pair
|
||||
pConfigKey = malloc(sizeof(*pConfigKey));
|
||||
if (pConfigKey)
|
||||
{
|
||||
pConfigKey->keyNameLen = strlen(pKey);
|
||||
pConfigKey->pKeyName = malloc(pConfigKey->keyNameLen + 1);
|
||||
if (pConfigKey->pKeyName)
|
||||
{
|
||||
// Save the key name in lower case
|
||||
LowerCaseString(pConfigKey->pKeyName, pKey);
|
||||
|
||||
pConfigKey->valueLen = strlen(pValue);
|
||||
pConfigKey->pValue = malloc(pConfigKey->valueLen + 1);
|
||||
if (pConfigKey->pValue)
|
||||
{
|
||||
strcpy(pConfigKey->pValue, pValue);
|
||||
|
||||
// The entry is ready, now associate it with the instance data.
|
||||
InsertTailList(&pConfigIfInstance->configKeyListHead, &pConfigKey->listEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0);
|
||||
free(pConfigKey->pKeyName);
|
||||
free(pConfigKey);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0);
|
||||
free(pConfigKey);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetConfigInterface- File seek error, errno = %d\n", errno);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0);
|
||||
|
||||
// Free the buffers associated with the instance data
|
||||
free(pConfigIfInstance->pConfigFolder);
|
||||
free(pConfigIfInstance);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0);
|
||||
|
||||
// Free the buffer allocated for the instance data
|
||||
free(pConfigIfInstance);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0);
|
||||
}
|
||||
|
||||
// Close the file
|
||||
fclose(pConfigFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(1, "-GetConfigInterface- Unable to open config file, errno = %d\n", errno);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetConfigInterface- Buffer allocation error\n", 0);
|
||||
}
|
||||
}
|
||||
|
||||
PlatReleaseMutex(g_configIfMutex);
|
||||
|
||||
DbgTrace(2, "-GetConfigInterface- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
ConfigIfInit(void)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Initializes the configuration interface complex.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
|
||||
DbgTrace(1, "-ConfigIfInit- Start\n", 0);
|
||||
|
||||
// Allocate mutex
|
||||
if ((g_configIfMutex = PlatAllocMutex()) != NULL)
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
else
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
|
||||
DbgTrace(1, "-ConfigIfInit- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
ConfigIfUninit(void)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Uninitializes the configuration interface complex.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
DbgTrace(1, "-ConfigIfUninit- Start\n", 0);
|
||||
|
||||
// Free mutex if necessary
|
||||
if (g_configIfMutex)
|
||||
{
|
||||
PlatDestroyMutex(g_configIfMutex);
|
||||
g_configIfMutex = NULL;
|
||||
}
|
||||
|
||||
DbgTrace(1, "-ConfigIfUninit- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
120
CASA-auth-token/server/AuthTokenValidate/config_if.h
Normal file
120
CASA-auth-token/server/AuthTokenValidate/config_if.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
#ifndef _CONFIG_IF_H_
|
||||
#define _CONFIG_IF_H_
|
||||
|
||||
|
||||
//===[ Include files ]=====================================================
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
/**************************************************************************
|
||||
***************************************************************************
|
||||
** **
|
||||
** Configuration Object Interface Definitions **
|
||||
** **
|
||||
***************************************************************************
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
int
|
||||
(SSCS_CALL *PFNConfiglIf_AddReference)(
|
||||
IN const void *pIfInstance);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Interface reference count.
|
||||
//
|
||||
// Description:
|
||||
// Increases interface reference count.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
void
|
||||
(SSCS_CALL *PFNConfiglIf_ReleaseReference)(
|
||||
IN const void *pIfInstance);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Nothing.
|
||||
//
|
||||
// Description:
|
||||
// Decreases interface reference count. The interface is deallocated if
|
||||
// the reference count becomes zero.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
char*
|
||||
(SSCS_CALL *PFNConfiglIf_GetEntryValue)(
|
||||
IN const void *pIfInstance,
|
||||
IN const char *pKeyName);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pKeyName -
|
||||
// Pointer to NULL terminated string that contains the
|
||||
// name of the key whose value is being requested.
|
||||
//
|
||||
// Returns:
|
||||
// Pointer to NULL terminated string with value being requested or NULL.
|
||||
//
|
||||
// Description:
|
||||
// Gets value associated with a key for the configuration object.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//
|
||||
// Config Interface Object
|
||||
//
|
||||
typedef struct _ConfigIf
|
||||
{
|
||||
PFNConfiglIf_AddReference addReference;
|
||||
PFNConfiglIf_ReleaseReference releaseReference;
|
||||
PFNConfiglIf_GetEntryValue getEntryValue;
|
||||
|
||||
} ConfigIf, *PConfigIf;
|
||||
|
||||
|
||||
#endif // #ifndef _CONFIG_IF_H_
|
||||
|
||||
@@ -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 = casa
|
||||
|
||||
DIST_SUBDIRS = casa
|
||||
|
||||
CFILES =
|
||||
|
||||
EXTRA_DIST = $(CFILES) *.h
|
||||
|
||||
.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
|
||||
|
||||
@@ -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) *.h
|
||||
|
||||
.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
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* README for casa_identoken
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
casa_identoken is the Identity Token Provider plug-in for tokens of type
|
||||
CasaIdentityToken. This are the default identity tokens utilized by CASA
|
||||
Authentication.
|
||||
|
||||
CONFIGURATION
|
||||
|
||||
The path to the casa_identoken plug-in is configured by placing the file
|
||||
CasaIdentityToken.conf in the /etc/opt/CASA/authtoken.d/modules.d folder.
|
||||
|
||||
PROGRAMMING NOTES
|
||||
|
||||
This module does not provide APIs to components outside of the CASA
|
||||
Authentication framework.
|
||||
|
||||
SECURITY CONSIDERATIONS
|
||||
|
||||
CasaIdentityTokens are embedded inside CASA Authentication Tokens. CasaIdentityTokens
|
||||
contain identity information which may be confidential and no attempts are made to
|
||||
ensure the confidentiality of the data. Because of this it is important that CASA
|
||||
Authentication Tokens be secured by applications making use of them. It is recommended
|
||||
that CASA authentication tokens be transmitted using SSL.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* TODO for casa_identoken
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
This file contains a list of the items still outstanding for casa_identoken.
|
||||
|
||||
OUTSTANDING ITEMS
|
||||
|
||||
None.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,346 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//
|
||||
// Identity Token Provider Interface instance data
|
||||
//
|
||||
typedef struct _IdenTokenProviderIfInstance
|
||||
{
|
||||
int refCount;
|
||||
IdenTokenProviderIf idenTokenProviderIf;
|
||||
|
||||
} IdenTokenProviderIfInstance, *PIdenTokenProviderIfInstance;
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
// IdenTokenProviderIf variables
|
||||
static
|
||||
int g_numIdenTokenProviderIfObjs = 0;
|
||||
|
||||
// Debug Level
|
||||
int DebugLevel = 0;
|
||||
|
||||
//
|
||||
// Initialization variables
|
||||
//
|
||||
static
|
||||
bool g_moduleInitialized = false;
|
||||
|
||||
// Synchronization mutex
|
||||
static
|
||||
HANDLE g_idenTokenProviderIfMutex = NULL;
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
int SSCS_CALL
|
||||
AddReference(
|
||||
IN const void *pIfInstance)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Interface reference count.
|
||||
//
|
||||
// Description:
|
||||
// Increases interface reference count.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
int refCount;
|
||||
IdenTokenProviderIfInstance *pIdenTokenProviderIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenProviderIfInstance, idenTokenProviderIf);
|
||||
|
||||
DbgTrace(2, "-AddReference- Start\n", 0);
|
||||
|
||||
// Increment the reference count on the object
|
||||
PlatAcquireMutex(g_idenTokenProviderIfMutex);
|
||||
pIdenTokenProviderIfInstance->refCount ++;
|
||||
refCount = pIdenTokenProviderIfInstance->refCount;
|
||||
PlatReleaseMutex(g_idenTokenProviderIfMutex);
|
||||
|
||||
DbgTrace(2, "-AddReference- End, refCount = %08X\n", refCount);
|
||||
|
||||
return refCount;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
void SSCS_CALL
|
||||
ReleaseReference(
|
||||
IN const void *pIfInstance)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Nothing.
|
||||
//
|
||||
// Description:
|
||||
// Decreases interface reference count. The interface is deallocated if
|
||||
// the reference count becomes zero.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
bool freeObj = false;
|
||||
IdenTokenProviderIfInstance *pIdenTokenProviderIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenProviderIfInstance, idenTokenProviderIf);
|
||||
|
||||
DbgTrace(2, "-ReleaseReference- Start\n", 0);
|
||||
|
||||
// Decrement the reference count on the object and determine if it needs to
|
||||
// be released.
|
||||
PlatAcquireMutex(g_idenTokenProviderIfMutex);
|
||||
pIdenTokenProviderIfInstance->refCount --;
|
||||
if (pIdenTokenProviderIfInstance->refCount == 0)
|
||||
{
|
||||
// The object needs to be released, forget about it.
|
||||
freeObj = true;
|
||||
g_numIdenTokenProviderIfObjs --;
|
||||
}
|
||||
PlatReleaseMutex(g_idenTokenProviderIfMutex);
|
||||
|
||||
// Free object if necessary
|
||||
if (freeObj)
|
||||
free(pIdenTokenProviderIfInstance);
|
||||
|
||||
DbgTrace(2, "-ReleaseReference- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
CasaStatus
|
||||
GetIdentityTokenIf(
|
||||
IN const void *pIfInstance,
|
||||
IN const char *pTokenBuf,
|
||||
IN const int tokenLen,
|
||||
INOUT IdenTokenIf **ppIdenTokenIf)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pTokenBuf -
|
||||
// Pointer to null terminated string containing an identity token.
|
||||
//
|
||||
// tokenLen -
|
||||
// Length of the token contained in the token buffer.
|
||||
//
|
||||
// ppIdenTokenIf -
|
||||
// Pointer to variable that will receive pointer to identity
|
||||
// token interface.
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Get identity token interface instance for the specified token.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
char *pDecodedTokenBuf;
|
||||
int decodedTokenBufLen;
|
||||
|
||||
DbgTrace(2, "-GetIdentityTokenIf- Start\n", 0);
|
||||
|
||||
// Validate input parameters
|
||||
if (pIfInstance == NULL
|
||||
|| pTokenBuf == NULL
|
||||
|| tokenLen == 0
|
||||
|| ppIdenTokenIf == NULL)
|
||||
{
|
||||
DbgTrace(0, "-GetIdentityTokenIf- Invalid input parameter\n", 0);
|
||||
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INVALID_PARAMETER);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// First decode the token string
|
||||
retStatus = DecodeData(pTokenBuf,
|
||||
tokenLen,
|
||||
(void**) &pDecodedTokenBuf,
|
||||
&decodedTokenBufLen);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// Get the identity token interface
|
||||
retStatus = GetIdenTokenInterface(pDecodedTokenBuf,
|
||||
decodedTokenBufLen,
|
||||
ppIdenTokenIf);
|
||||
|
||||
// Free the decoded token buffer
|
||||
free(pDecodedTokenBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetIdentityTokenIf- Token decode failure\n", 0);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
DbgTrace(2, "-GetIdentityTokenIf- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus SSCS_CALL
|
||||
GET_IDEN_TOKEN_PROVIDER_INTERFACE_RTN(
|
||||
IN const ConfigIf *pModuleConfigIf,
|
||||
INOUT IdenTokenProviderIf **ppIdenTokenProviderIf)
|
||||
//
|
||||
// Arguments:
|
||||
// pModuleConfigIf -
|
||||
// Pointer to configuration interface instance for the module.
|
||||
//
|
||||
// ppIdenTokenProviderIf -
|
||||
// Pointer to variable that will receive pointer to
|
||||
// IdentityTokenProviderIf instance.
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Gets identity token provider interface instance.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
IdenTokenProviderIfInstance *pIdenTokenProviderIfInstance;
|
||||
|
||||
DbgTrace(1, "-GetIdenTokenProviderInterface- Start\n", 0);
|
||||
|
||||
// Validate input parameters
|
||||
if (pModuleConfigIf == NULL
|
||||
|| ppIdenTokenProviderIf == NULL)
|
||||
{
|
||||
DbgTrace(0, "-GetIdenTokenProviderInterface- Invalid input parameter\n", 0);
|
||||
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_KRB5TOKEN,
|
||||
CASA_STATUS_INVALID_PARAMETER);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Make sure that the module has been initialized
|
||||
if (g_moduleInitialized == false)
|
||||
{
|
||||
// The module has not been initialized, synchronize access thought this section
|
||||
// to avoid having two threads performing initialization.
|
||||
AcquireModuleMutex;
|
||||
|
||||
// Assume success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
|
||||
// Check again in case another thread pre-empted us.
|
||||
if (g_moduleInitialized == false)
|
||||
{
|
||||
// Initialize the IdenTokenIf complex
|
||||
retStatus = IdenTokenIfInit();
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// Allocate mutex
|
||||
if ((g_idenTokenProviderIfMutex = PlatAllocMutex()) != NULL)
|
||||
{
|
||||
// Success
|
||||
g_moduleInitialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IdenTokenIfUninit();
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop synchronization
|
||||
ReleaseModuleMutex;
|
||||
|
||||
// Exit if we failed
|
||||
if (g_moduleInitialized == false)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Allocate space for the interface instance
|
||||
pIdenTokenProviderIfInstance = malloc(sizeof(*pIdenTokenProviderIfInstance));
|
||||
if (pIdenTokenProviderIfInstance)
|
||||
{
|
||||
// Initialize the interface instance data
|
||||
pIdenTokenProviderIfInstance->refCount = 1;
|
||||
pIdenTokenProviderIfInstance->idenTokenProviderIf.addReference = AddReference;
|
||||
pIdenTokenProviderIfInstance->idenTokenProviderIf.releaseReference = ReleaseReference;
|
||||
pIdenTokenProviderIfInstance->idenTokenProviderIf.getIdentityTokenIf = GetIdentityTokenIf;
|
||||
|
||||
// Keep track of this object
|
||||
PlatAcquireMutex(g_idenTokenProviderIfMutex);
|
||||
g_numIdenTokenProviderIfObjs ++;
|
||||
PlatReleaseMutex(g_idenTokenProviderIfMutex);
|
||||
|
||||
// Return the interface to the caller
|
||||
*ppIdenTokenProviderIf = &pIdenTokenProviderIfInstance->idenTokenProviderIf;
|
||||
|
||||
// Success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetIdenTokenProviderInterface- Buffer allocation failure\n", 0);
|
||||
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_KRB5TOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
DbgTrace(1, "-GetIdenTokenProviderInterface- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef _INTERNAL_H_
|
||||
#define _INTERNAL_H_
|
||||
|
||||
//===[ Include files ]=====================================================
|
||||
|
||||
#include "platform.h"
|
||||
#include <expat.h>
|
||||
#include <micasa_types.h>
|
||||
#include <casa_status.h>
|
||||
#include <casa_s_authtoken.h>
|
||||
#include "config_if.h"
|
||||
#include "iden_token_provider_if.h"
|
||||
#include "list_entry.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//===[ Inlines functions ]===============================================
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
//===[ Global externals ]==================================================
|
||||
|
||||
extern int DebugLevel;
|
||||
|
||||
//===[ External prototypes ]===============================================
|
||||
|
||||
//
|
||||
// Defined in identoken.c
|
||||
//
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
GetIdenTokenInterface(
|
||||
IN const char *pTokenBuf,
|
||||
IN const int tokenLen,
|
||||
INOUT IdenTokenIf **ppIdenTokenIf);
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
IdenTokenIfInit(void);
|
||||
|
||||
extern
|
||||
void
|
||||
IdenTokenIfUninit(void);
|
||||
|
||||
//
|
||||
// Defined in utils.c
|
||||
//
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
EncodeData(
|
||||
IN const void *pData,
|
||||
IN const int32_t dataLen,
|
||||
INOUT char **ppEncodedData,
|
||||
INOUT int32_t *pEncodedDataLen);
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
DecodeData(
|
||||
IN const char *pEncodedData,
|
||||
IN const int32_t encodedDataLen, // Does not include NULL terminator
|
||||
INOUT void **ppData,
|
||||
INOUT int32_t *pDataLen);
|
||||
|
||||
extern
|
||||
int
|
||||
dtoul(
|
||||
IN char *cp,
|
||||
IN int len);
|
||||
|
||||
//
|
||||
// Functions exported by platform.c
|
||||
//
|
||||
|
||||
extern
|
||||
HANDLE
|
||||
PlatAllocMutex(void);
|
||||
|
||||
extern
|
||||
void
|
||||
PlatDestroyMutex(HANDLE hMutex);
|
||||
|
||||
extern
|
||||
void
|
||||
PlatAcquireMutex(HANDLE hMutex);
|
||||
|
||||
extern
|
||||
void
|
||||
PlatReleaseMutex(HANDLE hMutex);
|
||||
|
||||
|
||||
//=========================================================================
|
||||
|
||||
#endif // _INTERNAL_H_
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#######################################################
|
||||
# #
|
||||
# CASA Authentication Token System configuration file #
|
||||
# for module: #
|
||||
# #
|
||||
# CasaIdentityToken #
|
||||
# #
|
||||
# Note: This module is the provider of Casa Identity #
|
||||
# tokens. #
|
||||
# #
|
||||
#######################################################
|
||||
|
||||
LibraryName /opt/novell/CASA/lib/casa_iden_token.so
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#######################################################################
|
||||
#
|
||||
# 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 = casa_iden_token
|
||||
MODULE_EXT = so
|
||||
|
||||
CFILES = $(srcdir)/identokenprovider.c \
|
||||
$(srcdir)/identoken.c \
|
||||
$(srcdir)/util.c \
|
||||
$(srcdir)/platform.c
|
||||
|
||||
CSFILES_CSC :=
|
||||
INCLUDES = -I. -I.. -I../../.. -I$(CASAROOT)/include -I../../../../../include
|
||||
RESOURCES =
|
||||
DEFINES = -Wno-format-extra-args -fno-strict-aliasing
|
||||
CFLAGS += $(INCLUDES) $(DEFINES)
|
||||
LIBS = -lpthread -ldl -lexpat
|
||||
LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT)
|
||||
|
||||
OBJDIR = ./$(TARGET_CFG)/$(LIB)
|
||||
OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o))
|
||||
|
||||
EXTRA_DIST = $(CFILES) *.h
|
||||
|
||||
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:
|
||||
if [ -d $(TARGET_CFG) ]; then rm -rf $(TARGET_CFG); fi
|
||||
|
||||
distclean-local:
|
||||
|
||||
maintainer-clean-local:
|
||||
rm -f Makefile.in
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//
|
||||
// Platform Mutex structure
|
||||
//
|
||||
typedef struct _PlatformMutex
|
||||
{
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
} PlatformMutex, *PPlatformMutex;
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
//
|
||||
// Module synchronization mutex
|
||||
//
|
||||
pthread_mutex_t g_hModuleMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
HANDLE
|
||||
PlatAllocMutex(void)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// Environment:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
PlatformMutex *pPlatMutex;
|
||||
pthread_mutexattr_t mutexAttr = {PTHREAD_MUTEX_RECURSIVE};
|
||||
|
||||
DbgTrace(2, "-PlatAllocMutex- Start\n", 0);
|
||||
|
||||
// Allocate space for our mutex structure
|
||||
pPlatMutex = malloc(sizeof(*pPlatMutex));
|
||||
if (pPlatMutex)
|
||||
{
|
||||
// Finish initializing the mutex
|
||||
pthread_mutex_init(&pPlatMutex->mutex, &mutexAttr);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-PlatAllocMutex- Memory allocation failure\n", 0);
|
||||
}
|
||||
|
||||
DbgTrace(2, "-PlatAllocMutex- End, retHandle = %08X\n", (unsigned int) pPlatMutex);
|
||||
|
||||
return (HANDLE) pPlatMutex;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
PlatDestroyMutex(HANDLE hMutex)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// Environment:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex;
|
||||
|
||||
DbgTrace(2, "-PlatDestroyMutex- Start\n", 0);
|
||||
|
||||
// Free the resources associated with the mutex
|
||||
pthread_mutex_destroy(&pPlatMutex->mutex);
|
||||
free(pPlatMutex);
|
||||
|
||||
DbgTrace(2, "-PlatDestroyMutex- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
PlatAcquireMutex(HANDLE hMutex)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// Environment:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex;
|
||||
|
||||
DbgTrace(2, "-PlatAcquireMutex- Start\n", 0);
|
||||
|
||||
// Acquire the mutex
|
||||
pthread_mutex_lock(&pPlatMutex->mutex);
|
||||
|
||||
DbgTrace(2, "-PlatAcquireMutex- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
PlatReleaseMutex(HANDLE hMutex)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// Environment:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex;
|
||||
|
||||
DbgTrace(2, "-PlatReleaseMutex- Start\n", 0);
|
||||
|
||||
// Release the mutex
|
||||
pthread_mutex_unlock(&pPlatMutex->mutex);
|
||||
|
||||
DbgTrace(2, "-PlatRelease- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 files ]=====================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
#define HANDLE void*
|
||||
|
||||
#ifndef CONTAINING_RECORD
|
||||
#define CONTAINING_RECORD(address, type, field) ((type *)( \
|
||||
(char*)(address) - \
|
||||
(char*)(&((type *)0)->field)))
|
||||
#endif
|
||||
|
||||
//
|
||||
// DbgTrace macro define
|
||||
//
|
||||
#define DbgTrace(LEVEL, X, Y) { \
|
||||
char printBuff[256]; \
|
||||
if (LEVEL == 0 || DebugLevel >= LEVEL) \
|
||||
{ \
|
||||
_snprintf(printBuff, sizeof(printBuff), X, Y); \
|
||||
fprintf(stderr, "CASA_IdenToken %s", printBuff); \
|
||||
} \
|
||||
}
|
||||
/*#define DbgTrace(LEVEL, X, Y) { \
|
||||
if (LEVEL == 0 || DebugLevel >= LEVEL) \
|
||||
{ \
|
||||
openlog("CASA_IdenToken", LOG_CONS | LOG_NOWAIT | LOG_ODELAY, LOG_USER); \
|
||||
syslog(LOG_USER | LOG_INFO, X, Y); \
|
||||
closelog(); \
|
||||
} \
|
||||
}*/
|
||||
|
||||
|
||||
// Deal with function name mapping issues
|
||||
#define _snprintf snprintf
|
||||
|
||||
|
||||
//
|
||||
// Module synchronization
|
||||
//
|
||||
extern pthread_mutex_t g_hModuleMutex;
|
||||
|
||||
#define AcquireModuleMutex pthread_mutex_lock(&g_hModuleMutex)
|
||||
#define ReleaseModuleMutex pthread_mutex_unlock(&g_hModuleMutex)
|
||||
|
||||
|
||||
//===[ Inlines functions ]===============================================
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global externals ]==================================================
|
||||
|
||||
//===[ External prototypes ]===============================================
|
||||
|
||||
//=========================================================================
|
||||
|
||||
@@ -0,0 +1,321 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
// Tables for Base64 encoding and decoding
|
||||
static const int8_t g_Base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static const uint8_t g_Expand64[256] =
|
||||
{
|
||||
/* ASCII table */
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
EncodeData(
|
||||
IN const void *pData,
|
||||
IN const int32_t dataLen,
|
||||
INOUT char **ppEncodedData,
|
||||
INOUT int32_t *pEncodedDataLen)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
int encodedSize;
|
||||
|
||||
char *pTmp;
|
||||
|
||||
DbgTrace(3, "-EncodeData- Start\n", 0);
|
||||
|
||||
// Determine the encoded size and allocate a buffer to hold the encoded data
|
||||
encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4;
|
||||
pTmp = (char*) malloc(encodedSize);
|
||||
*ppEncodedData = pTmp;
|
||||
if (*ppEncodedData)
|
||||
{
|
||||
uint8_t *pOut, *pIn;
|
||||
int i;
|
||||
|
||||
// Setup pointers to move through the buffers
|
||||
pIn = (uint8_t*) pData;
|
||||
pOut = (uint8_t*) *ppEncodedData;
|
||||
|
||||
// Perform the encoding
|
||||
for (i = 0; i < dataLen - 2; i += 3)
|
||||
{
|
||||
*pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F];
|
||||
*pOut++ = g_Base64[((pIn[i] & 0x3) << 4) |
|
||||
((int32_t)(pIn[i + 1] & 0xF0) >> 4)];
|
||||
*pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2) |
|
||||
((int32_t)(pIn[i + 2] & 0xC0) >> 6)];
|
||||
*pOut++ = g_Base64[pIn[i + 2] & 0x3F];
|
||||
}
|
||||
if (i < dataLen)
|
||||
{
|
||||
*pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F];
|
||||
if (i == (dataLen - 1))
|
||||
{
|
||||
*pOut++ = g_Base64[((pIn[i] & 0x3) << 4)];
|
||||
*pOut++ = '=';
|
||||
}
|
||||
else
|
||||
{
|
||||
*pOut++ = g_Base64[((pIn[i] & 0x3) << 4) |
|
||||
((int32_t)(pIn[i + 1] & 0xF0) >> 4)];
|
||||
*pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2)];
|
||||
}
|
||||
*pOut++ = '=';
|
||||
}
|
||||
*pOut++ = '\0';
|
||||
|
||||
// Return the encoded data length
|
||||
*pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData);
|
||||
|
||||
// Success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-EncodeData- Buffer allocation failure\n", 0);
|
||||
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
DbgTrace(3, "-EncodeData- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
DecodeData(
|
||||
IN const char *pEncodedData,
|
||||
IN const int32_t encodedDataLen, // Does not include NULL terminator
|
||||
INOUT void **ppData,
|
||||
INOUT int32_t *pDataLen)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
int i, j;
|
||||
int decodedSize;
|
||||
|
||||
DbgTrace(3, "-DecodeData- Start\n", 0);
|
||||
|
||||
// Determine the decoded size
|
||||
for (i = 0, j = 0; i < encodedDataLen; i++)
|
||||
if (g_Expand64[((uint8_t*) pEncodedData)[i]] < 64)
|
||||
j++;
|
||||
decodedSize = (j * 3 + 3) / 4;
|
||||
|
||||
// Allocate buffer to hold the decoded data
|
||||
*ppData = malloc(decodedSize);
|
||||
if (*ppData)
|
||||
{
|
||||
bool endReached = false;
|
||||
uint8_t c0, c1, c2, c3;
|
||||
uint8_t *p, *q;
|
||||
|
||||
// Initialize parameters that will be used during the decode operation
|
||||
c0 = c1 = c2 = c3 = 0;
|
||||
p = (uint8_t*) pEncodedData;
|
||||
q = (uint8_t*) *ppData;
|
||||
|
||||
// Decode the data
|
||||
//
|
||||
// Loop through the data, piecing back information. Any newlines, and/or
|
||||
// carriage returns need to be skipped.
|
||||
while (j > 4)
|
||||
{
|
||||
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
||||
p++;
|
||||
if (64 == g_Expand64[*p])
|
||||
{
|
||||
endReached = true;
|
||||
break;
|
||||
}
|
||||
c0 = *(p++);
|
||||
|
||||
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
||||
p++;
|
||||
if (64 == g_Expand64[*p])
|
||||
{
|
||||
*(q++) = (uint8_t)(g_Expand64[c0] << 2);
|
||||
j--;
|
||||
endReached = true;
|
||||
break;
|
||||
}
|
||||
c1 = *(p++);
|
||||
|
||||
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
||||
p++;
|
||||
if (64 == g_Expand64[*p])
|
||||
{
|
||||
*(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4);
|
||||
*(q++) = (uint8_t)(g_Expand64[c1] << 4);
|
||||
j -= 2;
|
||||
endReached = true;
|
||||
break;
|
||||
}
|
||||
c2 = *(p++);
|
||||
|
||||
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
||||
p++;
|
||||
if (64 == g_Expand64[*p])
|
||||
{
|
||||
*(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4);
|
||||
*(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2);
|
||||
*(q++) = (uint8_t)(g_Expand64[c2] << 6);
|
||||
j -= 3;
|
||||
endReached = true;
|
||||
break;
|
||||
}
|
||||
c3 = *(p++);
|
||||
|
||||
*(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4);
|
||||
*(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2);
|
||||
*(q++) = (uint8_t)(g_Expand64[c2] << 6 | g_Expand64[c3]);
|
||||
j -= 4;
|
||||
}
|
||||
if (!endReached)
|
||||
{
|
||||
if (j > 1)
|
||||
*(q++) = (uint8_t)(g_Expand64[*p] << 2 | g_Expand64[p[1]] >> 4);
|
||||
if (j > 2)
|
||||
*(q++) = (uint8_t)(g_Expand64[p[1]] << 4 | g_Expand64[p[2]] >> 2);
|
||||
if (j > 3)
|
||||
*(q++) = (uint8_t)(g_Expand64[p[2]] << 6 | g_Expand64[p[3]]);
|
||||
}
|
||||
|
||||
// Return the length of the decoded data
|
||||
*pDataLen = (int32_t)(q - (uint8_t*)*ppData);
|
||||
|
||||
// Success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-DecodeData- Buffer allocation failure\n", 0);
|
||||
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
DbgTrace(3, "-DecodeData- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
int
|
||||
dtoul(
|
||||
IN char *cp,
|
||||
IN int len)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L0
|
||||
//=======================================================================--
|
||||
{
|
||||
int n = 0;
|
||||
int i;
|
||||
|
||||
DbgTrace(2, "-dtoul- Start\n", 0);
|
||||
|
||||
for (i = 0; i < len; i++, cp++)
|
||||
{
|
||||
// Verify that we are dealing with a valid digit
|
||||
if (*cp >= '0' && *cp <= '9')
|
||||
{
|
||||
n = 10 * n + (*cp - '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-dtoul- Found invalid digit\n", 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DbgTrace(2, "-dtoul- End, result = %d\n", n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef _IDEN_TOKEN_PROVIDER_IF_H_
|
||||
#define _IDEN_TOKEN_PROVIDER_IF_H_
|
||||
|
||||
|
||||
//===[ Include files ]=====================================================
|
||||
|
||||
#include "config_if.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
***************************************************************************
|
||||
** **
|
||||
** Identity Token Interface Definitions **
|
||||
** **
|
||||
***************************************************************************
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
int
|
||||
(SSCS_CALL *PFNIdenTokenIf_AddReference)(
|
||||
IN const void *pIfInstance);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Interface reference count.
|
||||
//
|
||||
// Description:
|
||||
// Increases interface reference count.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
void
|
||||
(SSCS_CALL *PFNIdenTokenIf_ReleaseReference)(
|
||||
IN const void *pIfInstance);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Nothing.
|
||||
//
|
||||
// Description:
|
||||
// Decreases interface reference count. The interface is deallocated if
|
||||
// the reference count becomes zero.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
CasaStatus
|
||||
(SSCS_CALL *PFNIdenTokenIf_GetIdentityId)(
|
||||
IN const void *pIfInstance,
|
||||
INOUT char *pIdentIdBuf,
|
||||
INOUT int *pIdentIdLen);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pIdentIdBuf -
|
||||
// Pointer to buffer that will receive the identity id. The returned
|
||||
// id will be in the form of a NULL terminated string.
|
||||
//
|
||||
// pIdentIdBufLen -
|
||||
// Pointer to variable with the length of the buffer pointed by
|
||||
// pIdentIdBuf. On exit it contains the length of the returned id
|
||||
// (including the NULL terminator).
|
||||
//
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Get the identity id associated with the identity token.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
CasaStatus
|
||||
(SSCS_CALL *PFNIdenTokenIf_GetSourceName)(
|
||||
IN const void *pIfInstance,
|
||||
INOUT char *pSourceNameBuf,
|
||||
INOUT int *pSourceNameLen);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pSourceNameBuf -
|
||||
// Pointer to buffer that will receive the name associated with the
|
||||
// identity information source. The returned name will be in the form
|
||||
// of a NULL terminated string.
|
||||
//
|
||||
// pSourceNameBufLen -
|
||||
// Pointer to variable with the length of the buffer pointed by
|
||||
// pSourceNameBuf. On exit it contains the length of the returned
|
||||
// name (including the NULL terminator).
|
||||
//
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Get the name of the identity source associated with the identity token.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
CasaStatus
|
||||
(SSCS_CALL *PFNIdenTokenIf_GetSourceUrl)(
|
||||
IN const void *pIfInstance,
|
||||
INOUT char *pSourceUrlBuf,
|
||||
INOUT int *pSourceUrlLen);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pSourceUrlBuf -
|
||||
// Pointer to buffer that will receive the URL associated with the
|
||||
// identity information source. The returned URL will be in the form
|
||||
// of a NULL terminated string.
|
||||
//
|
||||
// pSourceUrlBufLen -
|
||||
// Pointer to variable with the length of the buffer pointed by
|
||||
// pSourceUrlBuf. On exit it contains the length of the returned
|
||||
// URL (including the NULL terminator).
|
||||
//
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Get the URL to the identity source associated with the identity token.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
CasaStatus
|
||||
(SSCS_CALL *PFNIdenTokenIf_AttributeEnumerate)(
|
||||
IN const void *pIfInstance,
|
||||
INOUT int *pEnumHandle,
|
||||
INOUT char *pAttribNameBuf,
|
||||
INOUT int *pAttribNameLen,
|
||||
INOUT char *pAttribValueBuf,
|
||||
INOUT int *pAttribValueLen);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pEnumHandle -
|
||||
// Pointer to enumeration handle. Must be set to 0 to start an
|
||||
// enumeration. Note the enumeration handle advances if the
|
||||
// function returns success.
|
||||
//
|
||||
// pAttribNameBuf -
|
||||
// Pointer to buffer that will receive the identity attribute name. The
|
||||
// returned name will be in the form of a NULL terminated string.
|
||||
//
|
||||
// pAttribNameLen -
|
||||
// Pointer to variable with the length of the buffer pointed by
|
||||
// pAttribNameBuf. On exit it contains the length of the returned
|
||||
// name (including the NULL terminator).
|
||||
//
|
||||
// pAttribValueBuf -
|
||||
// Pointer to buffer that will receive the identity attribute value. The
|
||||
// returned value will be in the form of a NULL terminated string.
|
||||
//
|
||||
// pAttribValueLen -
|
||||
// Pointer to variable with the length of the buffer pointed by
|
||||
// pAttribValueBuf. On exit it contains the length of the returned
|
||||
// value (including the NULL terminator).
|
||||
//
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Enumerates through the attributes associated with the identity token.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//
|
||||
// Identity Token Interface Object
|
||||
//
|
||||
typedef struct _IdenTokenIf
|
||||
{
|
||||
PFNIdenTokenIf_AddReference addReference;
|
||||
PFNIdenTokenIf_ReleaseReference releaseReference;
|
||||
PFNIdenTokenIf_GetIdentityId getIdentityId;
|
||||
PFNIdenTokenIf_GetSourceName getSourceName;
|
||||
PFNIdenTokenIf_GetSourceUrl getSourceUrl;
|
||||
PFNIdenTokenIf_AttributeEnumerate attributeEnumerate;
|
||||
|
||||
} IdenTokenIf, *PIdenTokenIf;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
***************************************************************************
|
||||
** **
|
||||
** Identity Token Provider Interface Definitions **
|
||||
** **
|
||||
***************************************************************************
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
int
|
||||
(SSCS_CALL *PFNIdenTokenProviderIf_AddReference)(
|
||||
IN const void *pIfInstance);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Interface reference count.
|
||||
//
|
||||
// Description:
|
||||
// Increases interface reference count.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
void
|
||||
(SSCS_CALL *PFNIdenTokenProviderIf_ReleaseReference)(
|
||||
IN const void *pIfInstance);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Nothing.
|
||||
//
|
||||
// Description:
|
||||
// Decreases interface reference count. The interface is deallocated if
|
||||
// the reference count becomes zero.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
CasaStatus
|
||||
(SSCS_CALL *PFNIdenTokenProviderIf_GetIdentityTokenIf)(
|
||||
IN const void *pIfInstance,
|
||||
IN const char *pTokenBuf,
|
||||
IN const int tokenLen,
|
||||
INOUT IdenTokenIf **ppIdenTokenIf);
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pTokenBuf -
|
||||
// Pointer to null terminated string containing an identity token.
|
||||
//
|
||||
// tokenLen -
|
||||
// Length of the token contained in the token buffer.
|
||||
//
|
||||
// ppIdenTokenIf -
|
||||
// Pointer to variable that will receive pointer to identity
|
||||
// token interface.
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Get identity token interface instance for the specified token.
|
||||
//=======================================================================--
|
||||
|
||||
|
||||
//
|
||||
// Identity Token Provider Interface Object
|
||||
//
|
||||
typedef struct _IdenTokenProviderIf
|
||||
{
|
||||
PFNIdenTokenProviderIf_AddReference addReference;
|
||||
PFNIdenTokenProviderIf_ReleaseReference releaseReference;
|
||||
PFNIdenTokenProviderIf_GetIdentityTokenIf getIdentityTokenIf;
|
||||
|
||||
} IdenTokenProviderIf, *PIdenTokenProviderIf;
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
typedef
|
||||
CasaStatus
|
||||
(SSCS_CALL *PFN_GetIdenTokenProviderIfRtn)(
|
||||
IN const ConfigIf *pModuleConfigIf,
|
||||
INOUT IdenTokenProviderIf **ppIdenTokenProviderIf);
|
||||
//
|
||||
// Arguments:
|
||||
// pModuleConfigIf -
|
||||
// Pointer to configuration interface instance for the module.
|
||||
//
|
||||
// ppIdenTokenProviderIf -
|
||||
// Pointer to variable that will receive pointer to
|
||||
// IdentityTokenProviderIf instance.
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Gets identity token provider interface instance.
|
||||
//=======================================================================--
|
||||
|
||||
#define GET_IDEN_TOKEN_PROVIDER_INTERFACE_RTN_SYMBOL "GetIdenTokenProviderInterface"
|
||||
#define GET_IDEN_TOKEN_PROVIDER_INTERFACE_RTN GetIdenTokenProviderInterface
|
||||
|
||||
|
||||
#endif // #ifndef _IDEN_TOKEN_PROVIDER_IF_H_
|
||||
|
||||
320
CASA-auth-token/server/AuthTokenValidate/identoken.c
Normal file
320
CASA-auth-token/server/AuthTokenValidate/identoken.c
Normal file
@@ -0,0 +1,320 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//
|
||||
// Identity Token Module definition
|
||||
//
|
||||
typedef struct _IdenTokenProviderModule
|
||||
{
|
||||
LIST_ENTRY listEntry;
|
||||
char *pTypeName;
|
||||
int typeNameLen;
|
||||
LIB_HANDLE libHandle;
|
||||
IdenTokenProviderIf *pIdenTokenProviderIf;
|
||||
|
||||
} IdenTokenProviderModule, *PIdenTokenProviderModule;
|
||||
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
//
|
||||
// IdenTokenProviderModule list and syncronization mutex
|
||||
//
|
||||
static
|
||||
LIST_ENTRY g_IdenTokenProviderModuleListHead = {&g_IdenTokenProviderModuleListHead, &g_IdenTokenProviderModuleListHead};
|
||||
|
||||
static
|
||||
HANDLE g_idenTokenMutex = NULL;
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
GetIdenTokenProviderInterface(
|
||||
IN const char *pIdenTokenTypeName,
|
||||
INOUT IdenTokenProviderIf **ppIdenTokenProviderIf)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// Environment:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
ConfigIf *pModuleConfigIf;
|
||||
|
||||
DbgTrace(2, "-GetIdenTokenProviderInterface- Start\n", 0);
|
||||
|
||||
// Get the configuration for the module
|
||||
retStatus = GetConfigInterface("/etc/opt/novell/CASA/authtoken.d/modules.d",
|
||||
pIdenTokenTypeName,
|
||||
&pModuleConfigIf);
|
||||
if (CASA_SUCCESS(retStatus)
|
||||
&& CasaStatusCode(retStatus) != CASA_STATUS_OBJECT_NOT_FOUND)
|
||||
{
|
||||
LIST_ENTRY *pListEntry;
|
||||
IdenTokenProviderModule *pIdenTokenProviderModule = NULL;
|
||||
int32_t idenTokenTypeNameLen = strlen(pIdenTokenTypeName);
|
||||
|
||||
// Gain exclusive access to our mutex
|
||||
PlatAcquireMutex(g_idenTokenMutex);
|
||||
|
||||
// Look if we already have the module in our list
|
||||
pListEntry = g_IdenTokenProviderModuleListHead.Flink;
|
||||
while (pListEntry != &g_IdenTokenProviderModuleListHead)
|
||||
{
|
||||
// Get pointer to the current entry
|
||||
pIdenTokenProviderModule = CONTAINING_RECORD(pListEntry, IdenTokenProviderModule, listEntry);
|
||||
|
||||
// Check if this is the module that we need
|
||||
if (pIdenTokenProviderModule->typeNameLen == idenTokenTypeNameLen
|
||||
&& memcmp(pIdenTokenTypeName, pIdenTokenProviderModule->pTypeName, idenTokenTypeNameLen) == 0)
|
||||
{
|
||||
// This is the module that we need, stop looking.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is not the module that we are looking for
|
||||
pIdenTokenProviderModule = NULL;
|
||||
}
|
||||
|
||||
// Advance to the next entry
|
||||
pListEntry = pListEntry->Flink;
|
||||
}
|
||||
|
||||
// Proceed based on whether or not a module was found
|
||||
if (pIdenTokenProviderModule)
|
||||
{
|
||||
// Module found in our list, provide the caller with its IdenTokenProviderIf
|
||||
// instance after we have incremented its reference count.
|
||||
pIdenTokenProviderModule->pIdenTokenProviderIf->addReference(pIdenTokenProviderModule->pIdenTokenProviderIf);
|
||||
*ppIdenTokenProviderIf = pIdenTokenProviderModule->pIdenTokenProviderIf;
|
||||
|
||||
// Success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Needed module not found in our list, create an entry.
|
||||
pIdenTokenProviderModule = malloc(sizeof(*pIdenTokenProviderModule));
|
||||
if (pIdenTokenProviderModule)
|
||||
{
|
||||
// Allocate buffer to contain the authentication type name within the module entry
|
||||
pIdenTokenProviderModule->pTypeName = malloc(idenTokenTypeNameLen + 1);
|
||||
if (pIdenTokenProviderModule->pTypeName)
|
||||
{
|
||||
char *pLibraryName;
|
||||
|
||||
// Initialize the library handle field
|
||||
pIdenTokenProviderModule->libHandle = NULL;
|
||||
|
||||
// Save the auth type name within the entry
|
||||
strcpy(pIdenTokenProviderModule->pTypeName, pIdenTokenTypeName);
|
||||
pIdenTokenProviderModule->typeNameLen = idenTokenTypeNameLen;
|
||||
|
||||
// Obtain the name of the library that we must load
|
||||
pLibraryName = pModuleConfigIf->getEntryValue(pModuleConfigIf, "LibraryName");
|
||||
if (pLibraryName)
|
||||
{
|
||||
// Load the library
|
||||
pIdenTokenProviderModule->libHandle = OpenLibrary(pLibraryName);
|
||||
if (pIdenTokenProviderModule->libHandle)
|
||||
{
|
||||
PFN_GetIdenTokenProviderIfRtn pGetIdenTokenProviderIfRtn;
|
||||
|
||||
// Library has been loaded, now get a pointer to its GetIdenTokenProviderProviderInterface routine
|
||||
pGetIdenTokenProviderIfRtn = (PFN_GetIdenTokenProviderIfRtn) GetFunctionPtr(pIdenTokenProviderModule->libHandle,
|
||||
GET_IDEN_TOKEN_PROVIDER_INTERFACE_RTN_SYMBOL);
|
||||
if (pGetIdenTokenProviderIfRtn)
|
||||
{
|
||||
// Now, obtain the modules IdenTokenProviderIf.
|
||||
retStatus = (pGetIdenTokenProviderIfRtn)(pModuleConfigIf, &pIdenTokenProviderModule->pIdenTokenProviderIf);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetIdenTokenProviderInterface- GetFunctionPtr error\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_LIBRARY_LOAD_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetIdenTokenProviderInterface- OpenLibrary error\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_LIBRARY_LOAD_FAILURE);
|
||||
}
|
||||
|
||||
// Free the buffer holding the library name
|
||||
free(pLibraryName);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetIdenTokenProviderInterface- Library name not configured\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_CONFIGURATION_ERROR);
|
||||
}
|
||||
|
||||
// Check if we were successful at obtaining the IdenTokenProviderIf instance for the
|
||||
// module.
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// Insert the entry in the list, provide the caller with its IdenTokenProviderIf
|
||||
// instance after we have incremented its reference count.
|
||||
InsertTailList(&g_IdenTokenProviderModuleListHead, &pIdenTokenProviderModule->listEntry);
|
||||
pIdenTokenProviderModule->pIdenTokenProviderIf->addReference(pIdenTokenProviderModule->pIdenTokenProviderIf);
|
||||
*ppIdenTokenProviderIf = pIdenTokenProviderModule->pIdenTokenProviderIf;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed, free resources.
|
||||
free(pIdenTokenProviderModule->pTypeName);
|
||||
if (pIdenTokenProviderModule->libHandle)
|
||||
CloseLibrary(pIdenTokenProviderModule->libHandle);
|
||||
free(pIdenTokenProviderModule);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetIdenTokenProviderInterface- Unable to allocate buffer\n", 0);
|
||||
|
||||
// Free buffer allocated for entry
|
||||
free(pIdenTokenProviderModule);
|
||||
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetIdenTokenProviderInterface- Unable to allocate buffer\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
}
|
||||
|
||||
// Release exclusive access to our mutex
|
||||
PlatReleaseMutex(g_idenTokenMutex);
|
||||
|
||||
// Release config interface instance
|
||||
pModuleConfigIf->releaseReference(pModuleConfigIf);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetIdenTokenProviderInterface- Unable to obtain config interface\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_CONFIGURATION_ERROR);
|
||||
}
|
||||
|
||||
DbgTrace(2, "-GetIdenTokenProviderInterface- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
IdenTokenInit(void)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Initializes the identity token complex.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
|
||||
DbgTrace(1, "-IdenTokenInit- Start\n", 0);
|
||||
|
||||
// Allocate mutex
|
||||
if ((g_idenTokenMutex = PlatAllocMutex()) != NULL)
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
else
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
|
||||
DbgTrace(1, "-IdenTokenInit- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
IdenTokenUninit(void)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Uninitializes the indentity token complex.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
DbgTrace(1, "-IdenTokenUninit- Start\n", 0);
|
||||
|
||||
// Free mutex if necessary
|
||||
if (g_idenTokenMutex)
|
||||
{
|
||||
PlatDestroyMutex(g_idenTokenMutex);
|
||||
g_idenTokenMutex = NULL;
|
||||
}
|
||||
|
||||
DbgTrace(1, "-IdenTokenUninit- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
222
CASA-auth-token/server/AuthTokenValidate/internal.h
Normal file
222
CASA-auth-token/server/AuthTokenValidate/internal.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef _INTERNAL_H_
|
||||
#define _INTERNAL_H_
|
||||
|
||||
//===[ Include files ]=====================================================
|
||||
|
||||
#include "platform.h"
|
||||
#include <expat.h>
|
||||
#include <micasa_types.h>
|
||||
#include <casa_status.h>
|
||||
#include <casa_s_authtoken.h>
|
||||
#include "proto.h"
|
||||
#include "list_entry.h"
|
||||
#include "config_if.h"
|
||||
#include "iden_token_provider_if.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//
|
||||
// Authentication Token structure
|
||||
//
|
||||
typedef struct _AuthToken
|
||||
{
|
||||
int tokenLifetime;
|
||||
char *pSignature;
|
||||
int signatureLen;
|
||||
char *pIdenTokenType;
|
||||
int idenTokenTypeLen;
|
||||
char *pIdenToken;
|
||||
int idenTokenLen;
|
||||
|
||||
} AuthToken, *PAuthToken;
|
||||
|
||||
|
||||
//===[ Inlines functions ]===============================================
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
//===[ Global externals ]==================================================
|
||||
|
||||
extern int DebugLevel;
|
||||
|
||||
//===[ External prototypes ]===============================================
|
||||
|
||||
//
|
||||
// Functions exported by config.c
|
||||
//
|
||||
extern
|
||||
CasaStatus
|
||||
GetConfigInterface(
|
||||
IN const char *pConfigFolder,
|
||||
IN const char *pConfigName,
|
||||
INOUT ConfigIf **ppConfigIf);
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
ConfigIfInit(void);
|
||||
|
||||
extern
|
||||
void
|
||||
ConfigIfUninit(void);
|
||||
|
||||
//
|
||||
// Functions exported by identoken.c
|
||||
//
|
||||
extern
|
||||
CasaStatus
|
||||
GetIdenTokenProviderInterface(
|
||||
IN const char *pIdenTokenTypeName,
|
||||
INOUT IdenTokenProviderIf **ppIdenTokenProviderIf);
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
IdenTokenInit(void);
|
||||
|
||||
extern
|
||||
void
|
||||
IdenTokenUninit(void);
|
||||
|
||||
//
|
||||
// Functions exported by platform.c
|
||||
//
|
||||
extern
|
||||
HANDLE
|
||||
PlatAllocMutex(void);
|
||||
|
||||
extern
|
||||
void
|
||||
PlatDestroyMutex(HANDLE hMutex);
|
||||
|
||||
extern
|
||||
void
|
||||
PlatAcquireMutex(HANDLE hMutex);
|
||||
|
||||
extern
|
||||
void
|
||||
PlatReleaseMutex(HANDLE hMutex);
|
||||
|
||||
extern
|
||||
LIB_HANDLE
|
||||
OpenLibrary(
|
||||
IN char *pFileName);
|
||||
|
||||
extern
|
||||
void
|
||||
CloseLibrary(
|
||||
IN LIB_HANDLE libHandle);
|
||||
|
||||
extern
|
||||
void*
|
||||
GetFunctionPtr(
|
||||
IN LIB_HANDLE libHandle,
|
||||
IN char *pFunctionName);
|
||||
|
||||
//
|
||||
// Functions exported by principal.c
|
||||
//
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
GetPrincipalInterface(
|
||||
IN IdenTokenIf *pIdenTokenIf,
|
||||
INOUT PrincipalIf **ppPrincipalIf);
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
PrincipalIfInit(void);
|
||||
|
||||
extern
|
||||
void
|
||||
PrincipalIfUninit(void);
|
||||
|
||||
//
|
||||
// Functions exported by validate.c
|
||||
//
|
||||
|
||||
extern
|
||||
CasaStatus SSCS_CALL
|
||||
ValidateAuthToken(
|
||||
IN const char *pServiceName,
|
||||
IN const char *pTokenBuf,
|
||||
IN const int tokenBufLen,
|
||||
INOUT PrincipalIf **ppPrincipalIf);
|
||||
|
||||
//
|
||||
// Functions exported by authtoken.c
|
||||
//
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
CreateAuthToken(
|
||||
IN char *pTokenBuf,
|
||||
IN int tokenBufLen,
|
||||
INOUT AuthToken **ppAuthToken);
|
||||
|
||||
extern
|
||||
void
|
||||
RelAuthToken(
|
||||
IN AuthToken *pAuthToken);
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
CheckAuthToken(
|
||||
IN AuthToken *pAuthToken,
|
||||
IN const char *pServiceName);
|
||||
|
||||
//
|
||||
// Defined in utils.c
|
||||
//
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
EncodeData(
|
||||
IN const void *pData,
|
||||
IN const int32_t dataLen,
|
||||
INOUT char **ppEncodedData,
|
||||
INOUT int32_t *pEncodedDataLen);
|
||||
|
||||
extern
|
||||
CasaStatus
|
||||
DecodeData(
|
||||
IN const char *pEncodedData,
|
||||
IN const int32_t encodedDataLen, // Does not include NULL terminator
|
||||
INOUT void **ppData,
|
||||
INOUT int32_t *pDataLen);
|
||||
|
||||
extern
|
||||
int
|
||||
dtoul(
|
||||
IN char *cp,
|
||||
IN int len);
|
||||
|
||||
|
||||
//=========================================================================
|
||||
|
||||
#endif // _INTERNAL_H_
|
||||
|
||||
115
CASA-auth-token/server/AuthTokenValidate/linux/Makefile.am
Normal file
115
CASA-auth-token/server/AuthTokenValidate/linux/Makefile.am
Normal file
@@ -0,0 +1,115 @@
|
||||
#######################################################################
|
||||
#
|
||||
# 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 = libcasa_s_authtoken
|
||||
MODULE_EXT = so
|
||||
|
||||
CFILES = $(srcdir)/config.c \
|
||||
$(srcdir)/authtoken.c \
|
||||
$(srcdir)/principal.c \
|
||||
$(srcdir)/util.c \
|
||||
$(srcdir)/validate.c \
|
||||
$(srcdir)/identoken.c \
|
||||
$(srcdir)/platform.c
|
||||
|
||||
CSFILES_CSC :=
|
||||
INCLUDES = -I. -I.. -I$(CASAROOT)/include -I../../../include
|
||||
RESOURCES =
|
||||
DEFINES = -Wno-format-extra-args -fno-strict-aliasing
|
||||
CFLAGS += $(INCLUDES) $(DEFINES)
|
||||
LIBS = -lpthread -ldl -lexpat
|
||||
LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT)
|
||||
|
||||
OBJDIR = ./$(TARGET_CFG)/$(LIB)
|
||||
OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o))
|
||||
|
||||
EXTRA_DIST = $(CFILES) *.h
|
||||
|
||||
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:
|
||||
if [ -d $(TARGET_CFG) ]; then rm -rf $(TARGET_CFG); fi
|
||||
|
||||
distclean-local:
|
||||
|
||||
maintainer-clean-local:
|
||||
rm -f Makefile.in
|
||||
|
||||
268
CASA-auth-token/server/AuthTokenValidate/linux/platform.c
Normal file
268
CASA-auth-token/server/AuthTokenValidate/linux/platform.c
Normal file
@@ -0,0 +1,268 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//
|
||||
// Platform Mutex structure
|
||||
//
|
||||
typedef struct _PlatformMutex
|
||||
{
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
} PlatformMutex, *PPlatformMutex;
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
//
|
||||
// Module synchronization mutex
|
||||
//
|
||||
pthread_mutex_t g_hModuleMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
HANDLE
|
||||
PlatAllocMutex(void)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// Environment:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
PlatformMutex *pPlatMutex;
|
||||
pthread_mutexattr_t mutexAttr = {PTHREAD_MUTEX_RECURSIVE};
|
||||
|
||||
DbgTrace(2, "-PlatAllocMutex- Start\n", 0);
|
||||
|
||||
// Allocate space for our mutex structure
|
||||
pPlatMutex = malloc(sizeof(*pPlatMutex));
|
||||
if (pPlatMutex)
|
||||
{
|
||||
// Finish initializing the mutex
|
||||
pthread_mutex_init(&pPlatMutex->mutex, &mutexAttr);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-PlatAllocMutex- Memory allocation failure\n", 0);
|
||||
}
|
||||
|
||||
DbgTrace(2, "-PlatAllocMutex- End, retHandle = %08X\n", (unsigned int) pPlatMutex);
|
||||
|
||||
return (HANDLE) pPlatMutex;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
PlatDestroyMutex(HANDLE hMutex)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// Environment:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex;
|
||||
|
||||
DbgTrace(2, "-PlatDestroyMutex- Start\n", 0);
|
||||
|
||||
// Free the resources associated with the mutex
|
||||
pthread_mutex_destroy(&pPlatMutex->mutex);
|
||||
free(pPlatMutex);
|
||||
|
||||
DbgTrace(2, "-PlatDestroyMutex- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
PlatAcquireMutex(HANDLE hMutex)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// Environment:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex;
|
||||
|
||||
DbgTrace(2, "-PlatAcquireMutex- Start\n", 0);
|
||||
|
||||
// Acquire the mutex
|
||||
pthread_mutex_lock(&pPlatMutex->mutex);
|
||||
|
||||
DbgTrace(2, "-PlatAcquireMutex- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
PlatReleaseMutex(HANDLE hMutex)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// Environment:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
PlatformMutex *pPlatMutex = (PlatformMutex*) hMutex;
|
||||
|
||||
DbgTrace(2, "-PlatReleaseMutex- Start\n", 0);
|
||||
|
||||
// Release the mutex
|
||||
pthread_mutex_unlock(&pPlatMutex->mutex);
|
||||
|
||||
DbgTrace(2, "-PlatRelease- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
LIB_HANDLE
|
||||
OpenLibrary(
|
||||
IN char *pFileName)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
LIB_HANDLE libHandle;
|
||||
|
||||
|
||||
DbgTrace(1, "-OpenLibrary- Start\n", 0);
|
||||
|
||||
libHandle = dlopen(pFileName, RTLD_LAZY);
|
||||
if (libHandle == NULL)
|
||||
{
|
||||
DbgTrace(0, "-OpenLibrary- Not able to load library, error = %d\n", dlerror());
|
||||
}
|
||||
|
||||
DbgTrace(1, "-OpenLibrary- End, handle = %08X\n", libHandle);
|
||||
|
||||
return libHandle;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
CloseLibrary(
|
||||
IN LIB_HANDLE libHandle)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
DbgTrace(1, "-CloseLibrary- Start\n", 0);
|
||||
|
||||
dlclose(libHandle);
|
||||
|
||||
DbgTrace(1, "-CloseLibrary- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void*
|
||||
GetFunctionPtr(
|
||||
IN LIB_HANDLE libHandle,
|
||||
IN char *pFunctionName)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
void *pFuncPtr;
|
||||
|
||||
DbgTrace(1, "-GetFunctionPtr- Start\n", 0);
|
||||
|
||||
pFuncPtr = dlsym(libHandle, pFunctionName);
|
||||
if (pFuncPtr == NULL)
|
||||
{
|
||||
DbgTrace(0, "-GetFunctionPtr- Not able to obtain func ptr, error = %d\n", dlerror());
|
||||
}
|
||||
|
||||
DbgTrace(1, "-GetFunctionPtr- End, pFuncPtr = %08X\n", pFuncPtr);
|
||||
|
||||
return pFuncPtr;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
100
CASA-auth-token/server/AuthTokenValidate/linux/platform.h
Normal file
100
CASA-auth-token/server/AuthTokenValidate/linux/platform.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 files ]=====================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
#define HANDLE void*
|
||||
|
||||
#ifndef CONTAINING_RECORD
|
||||
#define CONTAINING_RECORD(address, type, field) ((type *)( \
|
||||
(char*)(address) - \
|
||||
(char*)(&((type *)0)->field)))
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// DbgTrace macro define
|
||||
//
|
||||
#define DbgTrace(LEVEL, X, Y) { \
|
||||
char printBuff[256]; \
|
||||
if (LEVEL == 0 || DebugLevel >= LEVEL) \
|
||||
{ \
|
||||
_snprintf(printBuff, sizeof(printBuff), X, Y); \
|
||||
fprintf(stderr, "CASA_AuthTokenValidate %s", printBuff); \
|
||||
} \
|
||||
}
|
||||
/*#define DbgTrace(LEVEL, X, Y) { \
|
||||
if (LEVEL == 0 || DebugLevel >= LEVEL) \
|
||||
{ \
|
||||
openlog("CASA_AuthTokenValidate", LOG_CONS | LOG_NOWAIT | LOG_ODELAY, LOG_USER); \
|
||||
syslog(LOG_USER | LOG_INFO, X, Y); \
|
||||
closelog(); \
|
||||
} \
|
||||
}*/
|
||||
|
||||
|
||||
//
|
||||
// Deal with function name mapping issues
|
||||
//
|
||||
#define _snprintf snprintf
|
||||
|
||||
//
|
||||
// Module synchronization
|
||||
//
|
||||
extern pthread_mutex_t g_hModuleMutex;
|
||||
|
||||
#define AcquireModuleMutex pthread_mutex_lock(&g_hModuleMutex)
|
||||
#define ReleaseModuleMutex pthread_mutex_unlock(&g_hModuleMutex)
|
||||
|
||||
//
|
||||
// Other definitions
|
||||
//
|
||||
#define LIB_HANDLE void*
|
||||
|
||||
|
||||
//===[ Inlines functions ]===============================================
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global externals ]==================================================
|
||||
|
||||
//===[ External prototypes ]===============================================
|
||||
|
||||
//=========================================================================
|
||||
|
||||
482
CASA-auth-token/server/AuthTokenValidate/principal.c
Normal file
482
CASA-auth-token/server/AuthTokenValidate/principal.c
Normal file
@@ -0,0 +1,482 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//
|
||||
// Config Interface instance data
|
||||
//
|
||||
typedef struct _PrincipalIfInstance
|
||||
{
|
||||
int refCount;
|
||||
IdenTokenIf *pIdenTokenIf;
|
||||
PrincipalIf principalIf;
|
||||
|
||||
} PrincipalIfInstance, *PPrincipalIfInstance;
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
// PrincipalIf variables
|
||||
static
|
||||
int g_numPrincipalIfObjs = 0;
|
||||
|
||||
// Synchronization mutex
|
||||
static
|
||||
HANDLE g_principalIfMutex = NULL;
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
int SSCS_CALL
|
||||
AddReference(
|
||||
IN const void *pIfInstance)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Interface reference count.
|
||||
//
|
||||
// Description:
|
||||
// Increases interface reference count.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
int refCount;
|
||||
PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf);
|
||||
|
||||
DbgTrace(2, "-AddReference- Start\n", 0);
|
||||
|
||||
// Increment the reference count on the object
|
||||
PlatAcquireMutex(g_principalIfMutex);
|
||||
pPrincipalIfInstance->refCount ++;
|
||||
refCount = pPrincipalIfInstance->refCount;
|
||||
PlatReleaseMutex(g_principalIfMutex);
|
||||
|
||||
DbgTrace(2, "-AddReference- End, refCount = %08X\n", refCount);
|
||||
|
||||
return refCount;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
void SSCS_CALL
|
||||
ReleaseReference(
|
||||
IN const void *pIfInstance)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// Returns:
|
||||
// Nothing.
|
||||
//
|
||||
// Description:
|
||||
// Decreases interface reference count. The interface is deallocated if
|
||||
// the reference count becomes zero.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
bool freeObj = false;
|
||||
PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf);
|
||||
|
||||
DbgTrace(2, "-ReleaseReference- Start\n", 0);
|
||||
|
||||
// Decrement the reference count on the object and determine if it needs to
|
||||
// be released.
|
||||
PlatAcquireMutex(g_principalIfMutex);
|
||||
pPrincipalIfInstance->refCount --;
|
||||
if (pPrincipalIfInstance->refCount == 0)
|
||||
{
|
||||
// The object needs to be released, forget about it.
|
||||
freeObj = true;
|
||||
g_numPrincipalIfObjs --;
|
||||
}
|
||||
PlatReleaseMutex(g_principalIfMutex);
|
||||
|
||||
// Free object if necessary
|
||||
if (freeObj)
|
||||
{
|
||||
// Release the identity token interface associated with our instance
|
||||
pPrincipalIfInstance->pIdenTokenIf->releaseReference(pPrincipalIfInstance->pIdenTokenIf);
|
||||
|
||||
// Free our instance data
|
||||
free(pPrincipalIfInstance);
|
||||
}
|
||||
|
||||
DbgTrace(2, "-ReleaseReference- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
CasaStatus SSCS_CALL
|
||||
GetIdentityId(
|
||||
IN const void *pIfInstance,
|
||||
INOUT char *pIdentIdBuf,
|
||||
INOUT int *pIdentIdLen)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pIdentIdBuf -
|
||||
// Pointer to buffer that will receive the identity id. The returned
|
||||
// id will be in the form of a NULL terminated string.
|
||||
//
|
||||
// pIdentIdBufLen -
|
||||
// Pointer to variable with the length of the buffer pointed by
|
||||
// pIdentIdBuf. On exit it contains the length of the returned id
|
||||
// (including the NULL terminator).
|
||||
//
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Get the identity id associated with the identity token.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf);
|
||||
|
||||
DbgTrace(2, "-GetIdentityId- Start\n", 0);
|
||||
|
||||
// Just call into the identity token
|
||||
retStatus = pPrincipalIfInstance->pIdenTokenIf->getIdentityId(pPrincipalIfInstance->pIdenTokenIf,
|
||||
pIdentIdBuf,
|
||||
pIdentIdLen);
|
||||
|
||||
DbgTrace(2, "-GetIdentityId- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
CasaStatus SSCS_CALL
|
||||
GetSourceName(
|
||||
IN const void *pIfInstance,
|
||||
INOUT char *pSourceNameBuf,
|
||||
INOUT int *pSourceNameLen)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pSourceNameBuf -
|
||||
// Pointer to buffer that will receive the name associated with the
|
||||
// identity information source. The returned name will be in the form
|
||||
// of a NULL terminated string.
|
||||
//
|
||||
// pSourceNameBufLen -
|
||||
// Pointer to variable with the length of the buffer pointed by
|
||||
// pSourceNameBuf. On exit it contains the length of the returned
|
||||
// name (including the NULL terminator).
|
||||
//
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Get the name of the identity source associated with the identity token.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf);
|
||||
|
||||
DbgTrace(2, "-GetSourceName- Start\n", 0);
|
||||
|
||||
// Just call into the identity token
|
||||
retStatus = pPrincipalIfInstance->pIdenTokenIf->getSourceName(pPrincipalIfInstance->pIdenTokenIf,
|
||||
pSourceNameBuf,
|
||||
pSourceNameLen);
|
||||
|
||||
DbgTrace(2, "-GetSourceName- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
CasaStatus SSCS_CALL
|
||||
GetSourceUrl(
|
||||
IN const void *pIfInstance,
|
||||
INOUT char *pSourceUrlBuf,
|
||||
INOUT int *pSourceUrlLen)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pSourceUrlBuf -
|
||||
// Pointer to buffer that will receive the URL associated with the
|
||||
// identity information source. The returned URL will be in the form
|
||||
// of a NULL terminated string.
|
||||
//
|
||||
// pSourceUrlBufLen -
|
||||
// Pointer to variable with the length of the buffer pointed by
|
||||
// pSourceUrlBuf. On exit it contains the length of the returned
|
||||
// URL (including the NULL terminator).
|
||||
//
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Get the URL to the identity source associated with the identity token.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf);
|
||||
|
||||
DbgTrace(2, "-GetSourceUrl- Start\n", 0);
|
||||
|
||||
// Just call into the identity token
|
||||
retStatus = pPrincipalIfInstance->pIdenTokenIf->getSourceUrl(pPrincipalIfInstance->pIdenTokenIf,
|
||||
pSourceUrlBuf,
|
||||
pSourceUrlLen);
|
||||
|
||||
DbgTrace(2, "-GetSourceUrl- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
CasaStatus SSCS_CALL
|
||||
AttributeEnumerate(
|
||||
IN const void *pIfInstance,
|
||||
INOUT int *pEnumHandle,
|
||||
INOUT char *pAttribNameBuf,
|
||||
INOUT int *pAttribNameLen,
|
||||
INOUT char *pAttribValueBuf,
|
||||
INOUT int *pAttribValueLen)
|
||||
//
|
||||
// Arguments:
|
||||
// pIfInstance -
|
||||
// Pointer to interface object.
|
||||
//
|
||||
// pEnumHandle -
|
||||
// Pointer to enumeration handle. Must be set to 0 to start an
|
||||
// enumeration.
|
||||
//
|
||||
// pAttribNameBuf -
|
||||
// Pointer to buffer that will receive the identity attribute name. The
|
||||
// returned name will be in the form of a NULL terminated string.
|
||||
//
|
||||
// pAttribNameLen -
|
||||
// Pointer to variable with the length of the buffer pointed by
|
||||
// pAttribNameBuf. On exit it contains the length of the returned
|
||||
// name (including the NULL terminator).
|
||||
//
|
||||
// pAttribValueBuf -
|
||||
// Pointer to buffer that will receive the identity attribute value. The
|
||||
// returned value will be in the form of a NULL terminated string.
|
||||
//
|
||||
// pAttribValueLen -
|
||||
// Pointer to variable with the length of the buffer pointed by
|
||||
// pAttribValueBuf. On exit it contains the length of the returned
|
||||
// value (including the NULL terminator).
|
||||
//
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Enumerates through the attributes associated with the identity token.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
PrincipalIfInstance *pPrincipalIfInstance = CONTAINING_RECORD(pIfInstance, PrincipalIfInstance, principalIf);
|
||||
|
||||
DbgTrace(2, "-AttributeEnumerate- Start\n", 0);
|
||||
|
||||
// Just call into the identity token
|
||||
retStatus = pPrincipalIfInstance->pIdenTokenIf->attributeEnumerate(pPrincipalIfInstance->pIdenTokenIf,
|
||||
pEnumHandle,
|
||||
pAttribNameBuf,
|
||||
pAttribNameLen,
|
||||
pAttribValueBuf,
|
||||
pAttribValueLen);
|
||||
|
||||
DbgTrace(2, "-AttributeEnumerate- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
GetPrincipalInterface(
|
||||
IN IdenTokenIf *pIdenTokenIf,
|
||||
INOUT PrincipalIf **ppPrincipalIf)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Get principal interface instanced for the identity associated
|
||||
// with specified identity token.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
PrincipalIfInstance *pPrincipalIfInstance;
|
||||
CasaStatus retStatus;
|
||||
|
||||
DbgTrace(2, "-GetPrincipalInterface- Start\n", 0);
|
||||
|
||||
// Create a PrincipalIfInstance object for it.
|
||||
pPrincipalIfInstance = malloc(sizeof(*pPrincipalIfInstance));
|
||||
if (pPrincipalIfInstance)
|
||||
{
|
||||
// Initialize the PrincipalIf within the instance data
|
||||
pPrincipalIfInstance->principalIf.addReference = AddReference;
|
||||
pPrincipalIfInstance->principalIf.releaseReference = ReleaseReference;
|
||||
pPrincipalIfInstance->principalIf.getIdentityId = GetIdentityId;
|
||||
pPrincipalIfInstance->principalIf.getSourceName = GetSourceName;
|
||||
pPrincipalIfInstance->principalIf.getSourceUrl = GetSourceUrl;
|
||||
pPrincipalIfInstance->principalIf.attributeEnumerate = AttributeEnumerate;
|
||||
|
||||
// Keep reference to the identity token interface instance
|
||||
pPrincipalIfInstance->pIdenTokenIf = pIdenTokenIf;
|
||||
pIdenTokenIf->addReference(pIdenTokenIf);
|
||||
|
||||
// Return the PrincipalIf associated with the instance data after
|
||||
// incrementing its reference count.
|
||||
pPrincipalIfInstance->refCount ++;
|
||||
*ppPrincipalIf = &pPrincipalIfInstance->principalIf;
|
||||
|
||||
// Bump up our interface instance count
|
||||
PlatAcquireMutex(g_principalIfMutex);
|
||||
g_numPrincipalIfObjs ++;
|
||||
PlatReleaseMutex(g_principalIfMutex);
|
||||
|
||||
// Success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-GetPrincipalInterface- Buffer allocation failure\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
DbgTrace(2, "-GetPrincipalInterface- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
PrincipalIfInit(void)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Initializes the principal interface complex.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
|
||||
DbgTrace(1, "-PrincipalIfInit- Start\n", 0);
|
||||
|
||||
// Allocate mutex
|
||||
if ((g_principalIfMutex = PlatAllocMutex()) != NULL)
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
else
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
|
||||
DbgTrace(1, "-PrincipalIfInit- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
PrincipalIfUninit(void)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
// Casa Status
|
||||
//
|
||||
// Description:
|
||||
// Uninitializes the configuration interface complex.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
DbgTrace(1, "-PrincipalIfUninit- Start\n", 0);
|
||||
|
||||
// Free mutex if necessary
|
||||
if (g_principalIfMutex)
|
||||
{
|
||||
PlatDestroyMutex(g_principalIfMutex);
|
||||
g_principalIfMutex = NULL;
|
||||
}
|
||||
|
||||
DbgTrace(1, "-PrincipalIfUninit- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
321
CASA-auth-token/server/AuthTokenValidate/util.c
Normal file
321
CASA-auth-token/server/AuthTokenValidate/util.c
Normal file
@@ -0,0 +1,321 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
// Tables for Base64 encoding and decoding
|
||||
static const int8_t g_Base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static const uint8_t g_Expand64[256] =
|
||||
{
|
||||
/* ASCII table */
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
EncodeData(
|
||||
IN const void *pData,
|
||||
IN const int32_t dataLen,
|
||||
INOUT char **ppEncodedData,
|
||||
INOUT int32_t *pEncodedDataLen)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
int encodedSize;
|
||||
|
||||
char *pTmp;
|
||||
|
||||
DbgTrace(3, "-EncodeData- Start\n", 0);
|
||||
|
||||
// Determine the encoded size and allocate a buffer to hold the encoded data
|
||||
encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4;
|
||||
pTmp = (char*) malloc(encodedSize);
|
||||
*ppEncodedData = pTmp;
|
||||
if (*ppEncodedData)
|
||||
{
|
||||
uint8_t *pOut, *pIn;
|
||||
int i;
|
||||
|
||||
// Setup pointers to move through the buffers
|
||||
pIn = (uint8_t*) pData;
|
||||
pOut = (uint8_t*) *ppEncodedData;
|
||||
|
||||
// Perform the encoding
|
||||
for (i = 0; i < dataLen - 2; i += 3)
|
||||
{
|
||||
*pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F];
|
||||
*pOut++ = g_Base64[((pIn[i] & 0x3) << 4) |
|
||||
((int32_t)(pIn[i + 1] & 0xF0) >> 4)];
|
||||
*pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2) |
|
||||
((int32_t)(pIn[i + 2] & 0xC0) >> 6)];
|
||||
*pOut++ = g_Base64[pIn[i + 2] & 0x3F];
|
||||
}
|
||||
if (i < dataLen)
|
||||
{
|
||||
*pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F];
|
||||
if (i == (dataLen - 1))
|
||||
{
|
||||
*pOut++ = g_Base64[((pIn[i] & 0x3) << 4)];
|
||||
*pOut++ = '=';
|
||||
}
|
||||
else
|
||||
{
|
||||
*pOut++ = g_Base64[((pIn[i] & 0x3) << 4) |
|
||||
((int32_t)(pIn[i + 1] & 0xF0) >> 4)];
|
||||
*pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2)];
|
||||
}
|
||||
*pOut++ = '=';
|
||||
}
|
||||
*pOut++ = '\0';
|
||||
|
||||
// Return the encoded data length
|
||||
*pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData);
|
||||
|
||||
// Success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-EncodeData- Buffer allocation failure\n", 0);
|
||||
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
DbgTrace(3, "-EncodeData- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
DecodeData(
|
||||
IN const char *pEncodedData,
|
||||
IN const int32_t encodedDataLen, // Does not include NULL terminator
|
||||
INOUT void **ppData,
|
||||
INOUT int32_t *pDataLen)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
int i, j;
|
||||
int decodedSize;
|
||||
|
||||
DbgTrace(3, "-DecodeData- Start\n", 0);
|
||||
|
||||
// Determine the decoded size
|
||||
for (i = 0, j = 0; i < encodedDataLen; i++)
|
||||
if (g_Expand64[((uint8_t*) pEncodedData)[i]] < 64)
|
||||
j++;
|
||||
decodedSize = (j * 3 + 3) / 4;
|
||||
|
||||
// Allocate buffer to hold the decoded data
|
||||
*ppData = malloc(decodedSize);
|
||||
if (*ppData)
|
||||
{
|
||||
bool endReached = false;
|
||||
uint8_t c0, c1, c2, c3;
|
||||
uint8_t *p, *q;
|
||||
|
||||
// Initialize parameters that will be used during the decode operation
|
||||
c0 = c1 = c2 = c3 = 0;
|
||||
p = (uint8_t*) pEncodedData;
|
||||
q = (uint8_t*) *ppData;
|
||||
|
||||
// Decode the data
|
||||
//
|
||||
// Loop through the data, piecing back information. Any newlines, and/or
|
||||
// carriage returns need to be skipped.
|
||||
while (j > 4)
|
||||
{
|
||||
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
||||
p++;
|
||||
if (64 == g_Expand64[*p])
|
||||
{
|
||||
endReached = true;
|
||||
break;
|
||||
}
|
||||
c0 = *(p++);
|
||||
|
||||
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
||||
p++;
|
||||
if (64 == g_Expand64[*p])
|
||||
{
|
||||
*(q++) = (uint8_t)(g_Expand64[c0] << 2);
|
||||
j--;
|
||||
endReached = true;
|
||||
break;
|
||||
}
|
||||
c1 = *(p++);
|
||||
|
||||
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
||||
p++;
|
||||
if (64 == g_Expand64[*p])
|
||||
{
|
||||
*(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4);
|
||||
*(q++) = (uint8_t)(g_Expand64[c1] << 4);
|
||||
j -= 2;
|
||||
endReached = true;
|
||||
break;
|
||||
}
|
||||
c2 = *(p++);
|
||||
|
||||
while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p)))
|
||||
p++;
|
||||
if (64 == g_Expand64[*p])
|
||||
{
|
||||
*(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4);
|
||||
*(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2);
|
||||
*(q++) = (uint8_t)(g_Expand64[c2] << 6);
|
||||
j -= 3;
|
||||
endReached = true;
|
||||
break;
|
||||
}
|
||||
c3 = *(p++);
|
||||
|
||||
*(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4);
|
||||
*(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2);
|
||||
*(q++) = (uint8_t)(g_Expand64[c2] << 6 | g_Expand64[c3]);
|
||||
j -= 4;
|
||||
}
|
||||
if (!endReached)
|
||||
{
|
||||
if (j > 1)
|
||||
*(q++) = (uint8_t)(g_Expand64[*p] << 2 | g_Expand64[p[1]] >> 4);
|
||||
if (j > 2)
|
||||
*(q++) = (uint8_t)(g_Expand64[p[1]] << 4 | g_Expand64[p[2]] >> 2);
|
||||
if (j > 3)
|
||||
*(q++) = (uint8_t)(g_Expand64[p[2]] << 6 | g_Expand64[p[3]]);
|
||||
}
|
||||
|
||||
// Return the length of the decoded data
|
||||
*pDataLen = (int32_t)(q - (uint8_t*)*ppData);
|
||||
|
||||
// Success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-DecodeData- Buffer allocation failure\n", 0);
|
||||
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
DbgTrace(3, "-DecodeData- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
int
|
||||
dtoul(
|
||||
IN char *cp,
|
||||
IN int len)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
int n = 0;
|
||||
int i;
|
||||
|
||||
DbgTrace(2, "-dtoul- Start\n", 0);
|
||||
|
||||
for (i = 0; i < len; i++, cp++)
|
||||
{
|
||||
// Verify that we are dealing with a valid digit
|
||||
if (*cp >= '0' && *cp <= '9')
|
||||
{
|
||||
n = 10 * n + (*cp - '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-dtoul- Found invalid digit\n", 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DbgTrace(2, "-dtoul- End, result = %d\n", n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
244
CASA-auth-token/server/AuthTokenValidate/validate.c
Normal file
244
CASA-auth-token/server/AuthTokenValidate/validate.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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 "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
// Debug Level
|
||||
int DebugLevel = 0;
|
||||
|
||||
//
|
||||
// Initialization variables
|
||||
//
|
||||
static
|
||||
bool g_moduleInitialized = false;
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus SSCS_CALL
|
||||
ValidateAuthToken(
|
||||
IN const char *pServiceName,
|
||||
IN const char *pTokenBuf,
|
||||
IN const int tokenBufLen,
|
||||
INOUT PrincipalIf **ppPrincipalIf)
|
||||
//
|
||||
// Arguments:
|
||||
// pServiceName -
|
||||
// Pointer to NULL terminated string that contains the
|
||||
// name of the service targeted by the token.
|
||||
//
|
||||
// pTokenBuf -
|
||||
// Pointer to buffer that will receive the authentication
|
||||
// token. The length of this buffer is specified by the
|
||||
// pTokenBufLen parameter. Note that the the authentication
|
||||
// token will be in the form of a NULL terminated string.
|
||||
//
|
||||
// tokenBufLen -
|
||||
// Length of the data contained within the buffer pointed
|
||||
// at by pTokenBuf.
|
||||
//
|
||||
// ppPrincipalIf -
|
||||
// Pointer to variable that will receive a pointer to a principal
|
||||
// interface with information about the authenticated entity.
|
||||
// IMPORTANT NOTE: The caller is responsible for releasing the
|
||||
// interface after it is done with it to avoid a resource leak.
|
||||
//
|
||||
// Returns:
|
||||
// Casa status.
|
||||
//
|
||||
// Description:
|
||||
// Validates authentication token.
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
char *pDecodedTokenBuf;
|
||||
int decodedTokenBufLen;
|
||||
PrincipalIf *pPrincipalIf;
|
||||
|
||||
DbgTrace(1, "-ValidateAuthToken- Start\n", 0);
|
||||
|
||||
// Validate input parameters
|
||||
if (pServiceName == NULL
|
||||
|| pTokenBuf == NULL
|
||||
|| tokenBufLen == 0
|
||||
|| ppPrincipalIf == NULL)
|
||||
{
|
||||
DbgTrace(0, "-ValidateAuthToken- Invalid input parameter\n", 0);
|
||||
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INVALID_PARAMETER);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Make sure that the module has been initialized
|
||||
if (g_moduleInitialized == false)
|
||||
{
|
||||
// The module has not been initialized, synchronize access thought this section
|
||||
// to avoid having two threads performing initialization.
|
||||
AcquireModuleMutex;
|
||||
|
||||
// Assume success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
|
||||
// Check again in case another thread pre-empted us.
|
||||
if (g_moduleInitialized == false)
|
||||
{
|
||||
// Initialize the ConfigIf complex
|
||||
retStatus = ConfigIfInit();
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// Initialize the PrincipalIf complex
|
||||
retStatus = PrincipalIfInit();
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// Initialize the IdenToken complex
|
||||
retStatus = IdenTokenInit();
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// Success
|
||||
g_moduleInitialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
PrincipalIfUninit();
|
||||
ConfigIfUninit();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConfigIfUninit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop synchronization
|
||||
ReleaseModuleMutex;
|
||||
|
||||
// Exit if we failed
|
||||
if (g_moduleInitialized == false)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// First decode the token string
|
||||
retStatus = DecodeData(pTokenBuf,
|
||||
tokenBufLen,
|
||||
(void**) &pDecodedTokenBuf,
|
||||
&decodedTokenBufLen);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
AuthToken *pAuthToken;
|
||||
|
||||
// Token was decoded successfully, now create an authentication token object with it.
|
||||
retStatus = CreateAuthToken(pDecodedTokenBuf, decodedTokenBufLen, &pAuthToken);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// Now check the validity of the token
|
||||
retStatus = CheckAuthToken(pAuthToken, pServiceName);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
IdenTokenProviderIf *pIdenTokenProviderIf;
|
||||
|
||||
// The token was validated, now
|
||||
// Obtain Identity Token Provider interface
|
||||
retStatus = GetIdenTokenProviderInterface(pAuthToken->pIdenTokenType,
|
||||
&pIdenTokenProviderIf);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
IdenTokenIf *pIdenTokenIf;
|
||||
|
||||
// Use the Identity Token Provider to get an Identity Token Interface instance
|
||||
retStatus = pIdenTokenProviderIf->getIdentityTokenIf(pIdenTokenProviderIf,
|
||||
pAuthToken->pIdenToken,
|
||||
pAuthToken->idenTokenLen,
|
||||
&pIdenTokenIf);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// Now create a principal interface instance with the identity information present in
|
||||
// the identity token.
|
||||
retStatus = GetPrincipalInterface(pIdenTokenIf, &pPrincipalIf);
|
||||
if (CASA_SUCCESS(retStatus))
|
||||
{
|
||||
// Success, return the principal interface to the caller.
|
||||
*ppPrincipalIf = pPrincipalIf;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-ValidateAuthToken- Failed to instantiate principal interface\n", 0);
|
||||
}
|
||||
|
||||
// Release identity token interface
|
||||
pIdenTokenIf->releaseReference(pIdenTokenIf);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-ValidateAuthToken- Failed to instantiate identity token\n", 0);
|
||||
}
|
||||
|
||||
// Release identity token provider interface
|
||||
pIdenTokenProviderIf->releaseReference(pIdenTokenProviderIf);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-ValidateAuthToken- Failed to obtain identity token provider interface\n", 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Free the AuthToken object
|
||||
RelAuthToken(pAuthToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-ValidateAuthToken- Failed to create authentication token object\n", 0);
|
||||
}
|
||||
|
||||
// Free the decoded token buffer
|
||||
free(pDecodedTokenBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-ValidateAuthToken- Token decode failure\n", 0);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
DbgTrace(1, "-ValidateAuthToken- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
8
CASA-auth-token/server/JaasSupport/.classpath
Normal file
8
CASA-auth-token/server/JaasSupport/.classpath
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/CasaAuthServer"/>
|
||||
<classpathentry kind="lib" path="/usr/share/java/xerces-j2.jar"/>
|
||||
<classpathentry kind="output" path="build/classes"/>
|
||||
</classpath>
|
||||
17
CASA-auth-token/server/JaasSupport/.project
Normal file
17
CASA-auth-token/server/JaasSupport/.project
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>CasaJaasSupport</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
83
CASA-auth-token/server/JaasSupport/Makefile.am
Normal file
83
CASA-auth-token/server/JaasSupport/Makefile.am
Normal file
@@ -0,0 +1,83 @@
|
||||
#######################################################################
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
#######################################################################
|
||||
|
||||
SUBDIRS =
|
||||
DIST_SUBDIRS = src src/com src/com/novell src/com/novell/casa src/com/novell/casa/jaas
|
||||
|
||||
EXTRA_DIST = $(JAVAFILES)
|
||||
|
||||
CASAROOT = ../../..
|
||||
|
||||
CASALIBDIR = $(CASAROOT)/$(LIB)
|
||||
|
||||
#IDENT_ABSTRACTION_DIR = /home/jluciani/dev-local/bandit/trunk/IdentityAbstraction/build
|
||||
#IDENT_ABSTRACTION_DEPENDANCIES_DIR = /home/jluciani/dev-local/bandit/trunk/commons/bin
|
||||
|
||||
JAVAROOT = .
|
||||
JAVAC= javac
|
||||
|
||||
MODULE_NAME = CasaJaasSupport
|
||||
MODULE_EXT = jar
|
||||
|
||||
JAVAFILES = src/com/novell/casa/jaas/CasaLoginModule.java \
|
||||
src/com/novell/casa/jaas/CasaPrincipal.java
|
||||
|
||||
BUILDDIR = build
|
||||
|
||||
CLASSES = $(addprefix $(BUILDDIR)/, $(JAVAFILES:%.java=%.class))
|
||||
|
||||
LIBS =
|
||||
CLASSPATH = $(CASALIBDIR)/java/CasaAuthToken.jar:$(LIBS)
|
||||
|
||||
CUR_DIR := $(shell pwd)
|
||||
|
||||
all: $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT)
|
||||
|
||||
$(BUILDDIR)/%.class: %.java
|
||||
@echo [======== Compiling $@ ========]
|
||||
$(JAVAC) -sourcepath src -classpath $(CLASSPATH) -d $(BUILDDIR)/classes $<
|
||||
|
||||
$(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT): $(BUILDDIR) $(CLASSES)
|
||||
@echo [======== Jarring $@ ========]
|
||||
jar cvf $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT) -C $(BUILDDIR)/classes .
|
||||
cp $(BUILDDIR)/$(MODULE_NAME).$(MODULE_EXT) $(CASALIBDIR)/java/
|
||||
|
||||
$(BUILDDIR):
|
||||
[ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR)
|
||||
[ -d $(BUILDDIR)/classes ] || mkdir -p $(BUILDDIR)/classes
|
||||
[ -d $(CASALIBDIR) ] || mkdir -p $(CASALIBDIR)
|
||||
|
||||
install-exec-local:
|
||||
|
||||
uninstall-local:
|
||||
|
||||
#installcheck-local: install
|
||||
|
||||
clean-local:
|
||||
if [ -d $(BUILDDIR) ]; then rm -rf $(BUILDDIR); fi
|
||||
if [ -f $(CASALIBDIR)/java/$(MODULE_NAME).$(MODULE_EXT) ]; then rm -f $(CASALIBDIR)/java/$(MODULE_NAME).$(MODULE_EXT); fi
|
||||
|
||||
distclean-local:
|
||||
|
||||
maintainer-clean-local:
|
||||
rm -f Makefile.in
|
||||
rm -f Makefile
|
||||
|
||||
82
CASA-auth-token/server/JaasSupport/README
Normal file
82
CASA-auth-token/server/JaasSupport/README
Normal file
@@ -0,0 +1,82 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* README for JaasSupport
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
CasaLoginModule is a JAAS login module which can be configured
|
||||
to validate credentials consisting of CASA Authentication Tokens.
|
||||
|
||||
CONFIGURATION
|
||||
|
||||
To use CasaLoginModule for your service, set the java.security.auth.login.config
|
||||
property to point to the JAAS configuration file for your application. You must
|
||||
also set the org.xml.sax.driver property to point to an appropriate SAX Parser.
|
||||
The Xerces SAX Parser is a good option (org.apache.xerces.parsers.SAXParser).
|
||||
|
||||
The JAAS configuration file should include the following line:
|
||||
|
||||
com.novell.casa.jaas.CasaLoginModule Required;
|
||||
|
||||
The CasaLoginModule supports the following parameters:
|
||||
|
||||
PerformUsernameCheck - This parameter when set to true tells the CasaLoginModule
|
||||
that it must verify that the username is set to "CasaPrincipal". If the parameter
|
||||
is not specified the username is not checked.
|
||||
|
||||
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 JAAS Context.
|
||||
|
||||
SERVER PROGRAMMING NOTES
|
||||
|
||||
Server applications validating credentials containing CASA Authentication
|
||||
tokens can obtain information about the authenticated identity by getting
|
||||
access to the CasaPrincipal that gets associated with the Subject object
|
||||
returned from a successful JAAS login. The CasaPrincipal provides the
|
||||
following information: username, name of the identity data source (realm),
|
||||
and an URL to the identity data source. The CasaPrincipal also contains
|
||||
the attributes of the authenticated identity configured as required by the
|
||||
service in the Authentication Token Service.
|
||||
|
||||
EXAMPLE SERVER APPLICATION
|
||||
|
||||
See src/com/novell/casa/jaas/sample/SampleApp.java for an example application
|
||||
using JAAS to authenticate credentials consisting of CASA Authentication Tokens.
|
||||
|
||||
Note that to get the application to run you must set the path to the JAAS configuration
|
||||
file as the JAVA property java.security.auth.login.config. You must also make sure that
|
||||
the JAVA property org.xml.sax.driver.org is set to a valid SAX parser. The following shows
|
||||
the JAVA options that you would set to run the test application: -Djava.security.auth.login.
|
||||
config=/home/user/SampleApp/SampleApp.conf -Dorg.xml.sax.driver=org.apache.xerces.parsers.
|
||||
SAXParser
|
||||
|
||||
The SampleApp.conf file should have the following contents:
|
||||
|
||||
SampleApp {
|
||||
com.novell.casa.jaas.CasaLoginModule Required debug=true;
|
||||
};
|
||||
|
||||
You must also include the CasaJaasSupport.jar and CasaAuthToken.jar files in the
|
||||
CLASSPATH of the application.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
13
CASA-auth-token/server/JaasSupport/TODO
Normal file
13
CASA-auth-token/server/JaasSupport/TODO
Normal file
@@ -0,0 +1,13 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* TODO for JaasSupport
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
INTRODUCTION
|
||||
|
||||
This file contains a list of the items still outstanding for JaasSupport.
|
||||
|
||||
OUTSTANDING ITEMS
|
||||
|
||||
- Change printfs used for debugging into a suitable mechanism.
|
||||
17
CASA-auth-token/server/JaasSupport/make_and_run_test.sh
Executable file
17
CASA-auth-token/server/JaasSupport/make_and_run_test.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
if [ ! -d build-test ]; then
|
||||
mkdir build-test
|
||||
mkdir build-test/classes
|
||||
else
|
||||
if [ ! -d build-test/classes ]; then
|
||||
mkdir build-test/classes
|
||||
fi
|
||||
fi
|
||||
echo "*** Compiling the test application ***"
|
||||
javac -sourcepath src -classpath ../../../lib/java/CasaJaasSupport.jar:../../../lib/java/CasaAuthToken.jar -d build-test/classes src/com/novell/casa/jaas/sample/SampleApp.java src/com/novell/casa/jaas/sample/SampleAppCallbackHandler.java
|
||||
echo "*** Done compiling ***"
|
||||
echo ""
|
||||
echo "*** Starting the test application ***"
|
||||
java -classpath build-test/classes:../../../lib/java/CasaJaasSupport.jar:../../../lib/java/CasaAuthToken.jar:/usr/share/java/xerces-j2.jar -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser -Djava.security.auth.login.config=src/com/novell/casa/jaas/sample/SampleApp.conf com.novell.casa.jaas.sample.SampleApp
|
||||
#jdb -sourcepath src:../AuthTokenSvc/src -classpath build-test/classes:../../../lib/java/CasaJaasSupport.jar:../../../lib/java/CasaAuthToken.jar:/usr/share/java/xerces-j2.jar -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser -Djava.security.auth.login.config=src/com/novell/casa/jaas/sample/SampleApp.conf com.novell.casa.jaas.sample.SampleApp
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.jaas;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.security.auth.Subject;
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.NameCallback;
|
||||
import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.login.FailedLoginException;
|
||||
import javax.security.auth.login.LoginException;
|
||||
import javax.security.auth.spi.LoginModule;
|
||||
|
||||
import com.novell.casa.authtoksvc.AuthToken;
|
||||
import com.novell.casa.authtoksvc.CasaIdentityToken;
|
||||
|
||||
/*
|
||||
* CasaLoginModule Class.
|
||||
*
|
||||
* This class implements a LoginModule which performs
|
||||
* authentication via the Casa Authentication Token
|
||||
* infrastructure.
|
||||
*
|
||||
*/
|
||||
public class CasaLoginModule implements LoginModule
|
||||
{
|
||||
private final static String casaUsername = "CasaIdentityUser";
|
||||
|
||||
private Subject m_subject = null;
|
||||
private CasaPrincipal m_principal = null;
|
||||
private CallbackHandler m_callbackHandler = null;
|
||||
private Map m_sharedState = null;
|
||||
private Map m_options = null;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see javax.security.auth.spi.LoginModule#abort()
|
||||
*/
|
||||
public boolean abort() throws LoginException
|
||||
{
|
||||
// Clear out all of our state
|
||||
m_subject = null;
|
||||
m_principal = null;
|
||||
m_callbackHandler = null;
|
||||
m_sharedState = null;
|
||||
m_options = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see javax.security.auth.spi.LoginModule#commit()
|
||||
*/
|
||||
public boolean commit() throws LoginException
|
||||
{
|
||||
// Check if we instantiated a principal to associate
|
||||
// with the subject.
|
||||
if (m_principal != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Add our principal to the set associated with
|
||||
// the subject.
|
||||
m_subject.getPrincipals().add(m_principal);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("CasaLoginModule.commit()- Exception caught associating principal, msg: " + e.getMessage());
|
||||
throw new LoginException("Error encountered");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allways return since authentication failed or was not
|
||||
// performed by us.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see javax.security.auth.spi.LoginModule#login()
|
||||
*/
|
||||
public boolean login() throws LoginException
|
||||
{
|
||||
// Verify that a CallbackHandler was specified
|
||||
if (m_callbackHandler == null)
|
||||
{
|
||||
System.err.println("CasaLoginModule.login()- Null CallbackHandler");
|
||||
throw new LoginException("Null CallbackHandler");
|
||||
}
|
||||
|
||||
// Do not perform the username check unless configured to do it.
|
||||
boolean performUsernameCheck = false;
|
||||
if (m_options != null
|
||||
&& m_options.containsKey((String) "PerformUsernameCheck") == true)
|
||||
{
|
||||
String keyVal = (String) m_options.get("PerformUsernameCheck");
|
||||
if (keyVal != null && keyVal.equals("true"))
|
||||
performUsernameCheck = true;
|
||||
}
|
||||
|
||||
if (performUsernameCheck)
|
||||
{
|
||||
// Verify that the username is CasaIdentityUser, for this
|
||||
// we first need to obtain it.
|
||||
//
|
||||
// Try to obtain the user name from the shared state
|
||||
String username = (String) m_sharedState.get("javax.security.auth.login.name");
|
||||
if (username == null)
|
||||
{
|
||||
// The usename was not stored in the shared state, request it.
|
||||
try
|
||||
{
|
||||
NameCallback nameCallback = new NameCallback("Enter username:");
|
||||
Callback[] callbacks = new Callback[1];
|
||||
callbacks[0] = nameCallback;
|
||||
m_callbackHandler.handle(callbacks);
|
||||
username = nameCallback.getName();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("CasaLoginModule.login()- Exception caught during nameCallback, msg: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Check the username
|
||||
if (username == null)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
// Save the retrieved username in the shared state and then check it.
|
||||
m_sharedState.put("javax.security.auth.login.name", username);
|
||||
if (username.equals(casaUsername) == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check the username
|
||||
if (username.equals(casaUsername) == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Obtain the CasaAuthenticationToken
|
||||
char[] authTokenChars = null;
|
||||
try
|
||||
{
|
||||
PasswordCallback passwordCallback = new PasswordCallback("Enter CasaAuthenticationToken:", false);
|
||||
Callback[] callbacks = new Callback[1];
|
||||
callbacks[0] = passwordCallback;
|
||||
m_callbackHandler.handle(callbacks);
|
||||
authTokenChars = passwordCallback.getPassword();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("CasaLoginModule.login()- Exception caught during passwordCallback, msg: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Check the CasaAuthenticationToken
|
||||
if (authTokenChars != null)
|
||||
{
|
||||
// Instantiate the AuthToken, this validates the token itself.
|
||||
try
|
||||
{
|
||||
AuthToken authToken = new AuthToken(new String(authTokenChars));
|
||||
|
||||
// Instantiate the appropriate IdentityToken based on the IdentityTokenProvider type
|
||||
// tbd - For now use the CasaIdentityToken
|
||||
CasaIdentityToken identityToken = new CasaIdentityToken();
|
||||
identityToken.initialize(authToken.getIdentityToken());
|
||||
|
||||
// Now instantiate the CasaPrincipal
|
||||
m_principal = new CasaPrincipal(identityToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// The validation of one of the tokens failed
|
||||
// tbd - Log
|
||||
System.err.println("CasaLoginModule.login()- Exception caught during token processing, msg: " + e.getMessage());
|
||||
throw new FailedLoginException("Token validation failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Token not provided
|
||||
// tbd - Log
|
||||
System.err.println("CasaLoginModule.login()- Token not provided");
|
||||
throw new FailedLoginException("CasaAuthenticationToken not obtained");
|
||||
}
|
||||
|
||||
// User validated
|
||||
// tbd - Log
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see javax.security.auth.spi.LoginModule#logout()
|
||||
*/
|
||||
public boolean logout() throws LoginException
|
||||
{
|
||||
// Check if we must try to remove our principal
|
||||
// from the associated subject.
|
||||
if (m_principal != null
|
||||
&& m_subject.isReadOnly() == false)
|
||||
{
|
||||
Set principalSet = m_subject.getPrincipals();
|
||||
principalSet.remove(m_principal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map)
|
||||
*/
|
||||
public void initialize(
|
||||
Subject subject,
|
||||
CallbackHandler callbackHandler,
|
||||
Map sharedState,
|
||||
Map options)
|
||||
{
|
||||
// Save the input parameters for later use
|
||||
m_subject = subject;
|
||||
m_callbackHandler = callbackHandler;
|
||||
m_sharedState = sharedState;
|
||||
m_options = options;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.jaas;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
import com.novell.casa.authtoksvc.IdentityToken;
|
||||
|
||||
/*
|
||||
* CasaPrincipal class.
|
||||
*
|
||||
* This class implements the principal class for
|
||||
* identities authenticated by Casa.
|
||||
*
|
||||
*/
|
||||
public class CasaPrincipal implements Principal
|
||||
{
|
||||
private String m_name;
|
||||
private String m_realm;
|
||||
private String m_identStoreUrl;
|
||||
private javax.naming.directory.Attributes m_attributes;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
public CasaPrincipal(IdentityToken identityToken) throws Exception
|
||||
{
|
||||
// Get the necessary information from the identity token
|
||||
m_name = identityToken.getIdentityId();
|
||||
m_realm = identityToken.getSourceName();
|
||||
m_identStoreUrl = identityToken.getSourceUrl();
|
||||
m_attributes = identityToken.getAttributes();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.security.Principal#getName()
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the name associated with the source of the identity data.
|
||||
*/
|
||||
public String getRealm()
|
||||
{
|
||||
return m_realm;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the url associated with the source of the identity data.
|
||||
*/
|
||||
public String getIdentStoreUrl()
|
||||
{
|
||||
return m_identStoreUrl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the identity attributes.
|
||||
*/
|
||||
public javax.naming.directory.Attributes getAttributes()
|
||||
{
|
||||
return m_attributes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
testService {
|
||||
com.novell.casa.jaas.CasaLoginModule Required debug=true;
|
||||
};
|
||||
@@ -0,0 +1,193 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.jaas.sample;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.naming.NamingEnumeration;
|
||||
import javax.security.auth.Subject;
|
||||
import javax.security.auth.login.LoginContext;
|
||||
import javax.security.auth.login.LoginException;
|
||||
|
||||
import com.novell.casa.jaas.CasaPrincipal;
|
||||
|
||||
|
||||
/*
|
||||
* This is a sample application which demonstrates the use of
|
||||
* JAAS and Casa to authenticate a connection.
|
||||
*/
|
||||
public class SampleApp
|
||||
{
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
{
|
||||
Socket sock = null;
|
||||
ServerSocket listenSock = null;
|
||||
|
||||
try
|
||||
{
|
||||
// Create a socket to listen for connections
|
||||
int port = 4444;
|
||||
int queueLen = 6;
|
||||
System.out.println("Listen port = " + port);
|
||||
listenSock = new ServerSocket(port, queueLen);
|
||||
|
||||
// Service connections
|
||||
while (true)
|
||||
{
|
||||
BufferedReader in = null;
|
||||
try
|
||||
{
|
||||
// Wait for the next connection
|
||||
System.out.println("Waiting for connection");
|
||||
sock = listenSock.accept();
|
||||
System.out.println();
|
||||
System.out.println("********Connection received*********");
|
||||
|
||||
// Get socket I/O streams
|
||||
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
|
||||
//PrintStream out = new PrintStream(sock.getOutputStream());
|
||||
|
||||
// Get the authentication token from the client
|
||||
String authToken = in.readLine();
|
||||
//System.out.println("Token received from client, length = " + authToken.length());
|
||||
|
||||
// Authenticate the token and print out the information available to our service
|
||||
// about the authenticated identity.
|
||||
LoginContext lc = new LoginContext("testService", new SampleAppCallbackHandler(authToken));
|
||||
try
|
||||
{
|
||||
System.out.println("Authenticating the user");
|
||||
lc.login();
|
||||
|
||||
System.out.println(" Authentication succeeded");
|
||||
|
||||
// Now get the subject associated with the context
|
||||
Subject subject = lc.getSubject();
|
||||
|
||||
// Now get the CasaPrincipals that represent the authenticated
|
||||
// identity or identities.
|
||||
Set principalSet = subject.getPrincipals(CasaPrincipal.class);
|
||||
//System.out.println("The number of CasaPrincipals is: " + principalSet.size());
|
||||
Iterator principalIter = principalSet.iterator();
|
||||
System.out.println();
|
||||
System.out.println("Authenticated Identity Information");
|
||||
System.out.println();
|
||||
while (principalIter.hasNext() == true)
|
||||
{
|
||||
CasaPrincipal principal = (CasaPrincipal) principalIter.next();
|
||||
|
||||
// Print out information about the principal
|
||||
System.out.println(" Source of the identity information: " + principal.getIdentStoreUrl());
|
||||
System.out.println(" Realm name associated with identity source: " + principal.getRealm());
|
||||
System.out.println(" Principal name (unique within identity source realm): " + principal.getName());
|
||||
System.out.println();
|
||||
System.out.println("Authenticated Identity Attributes");
|
||||
System.out.println();
|
||||
javax.naming.directory.Attributes attrs = principal.getAttributes();
|
||||
for (NamingEnumeration ae = attrs.getAll(); ae.hasMore();)
|
||||
{
|
||||
javax.naming.directory.Attribute attr = (javax.naming.directory.Attribute) ae.next();
|
||||
|
||||
NamingEnumeration enumeration = attr.getAll();
|
||||
while (enumeration.hasMore())
|
||||
{
|
||||
System.out.print(" Attribute Name: " + attr.getID());
|
||||
Object attrValue = enumeration.next();
|
||||
if (attrValue instanceof byte[])
|
||||
{
|
||||
// The attribute value is binary data
|
||||
StringBuffer buf = new StringBuffer();
|
||||
char[] hex = "0123456789ABCDEF".toCharArray();
|
||||
for (int i = 0; i < ((byte[]) attrValue).length; i++)
|
||||
{
|
||||
buf.append(hex[(((byte[]) attrValue)[i] >> 4) & 0xF]);
|
||||
buf.append(hex[((byte[]) attrValue)[i] & 0xF]);
|
||||
}
|
||||
System.out.println(" :: Attribute Value: " + buf.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// The attribute value is contained in a string
|
||||
System.out.println(" :: Attribute Value: " + (String) attrValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
catch (LoginException e)
|
||||
{
|
||||
System.out.println(" Authentication failed, LoginException: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (sock != null)
|
||||
{
|
||||
sock.close();
|
||||
sock = null;
|
||||
}
|
||||
if (in != null)
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.out.println("IOException: " + e.getMessage());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.out.println("Exception: " + e.getMessage());
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sock != null)
|
||||
{
|
||||
sock.close();
|
||||
}
|
||||
if (listenSock != null)
|
||||
{
|
||||
listenSock.close();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.out.println("Exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
package com.novell.casa.jaas.sample;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.NameCallback;
|
||||
import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
|
||||
|
||||
public class SampleAppCallbackHandler implements CallbackHandler
|
||||
{
|
||||
private String m_authToken;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
public SampleAppCallbackHandler(String authToken)
|
||||
{
|
||||
m_authToken = authToken;
|
||||
}
|
||||
|
||||
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
|
||||
{
|
||||
for (int i = 0; i < callbacks.length; i++)
|
||||
{
|
||||
if (callbacks[i] instanceof NameCallback) {
|
||||
NameCallback nc = (NameCallback) callbacks[i];
|
||||
nc.setName("CasaIdentityUser");
|
||||
} else if (callbacks[i] instanceof PasswordCallback) {
|
||||
PasswordCallback pc = (PasswordCallback) callbacks[i];
|
||||
//System.out.println("SampleAppCallbackHandler.handle()- Token length = " + m_authToken.length());
|
||||
char[] allChars = m_authToken.toCharArray();
|
||||
|
||||
// Remove the null terminator
|
||||
char[] tokenChars = new char[allChars.length - 1];
|
||||
for (int ii = 0; ii < tokenChars.length; ii++)
|
||||
tokenChars[ii] = allChars[ii];
|
||||
pc.setPassword(tokenChars);
|
||||
} else {
|
||||
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
CASA-auth-token/server/Makefile.am
Normal file
37
CASA-auth-token/server/Makefile.am
Normal 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 = AuthTokenValidate ApacheSupport PamSupport AuthTokenSvc JaasSupport
|
||||
|
||||
DIST_SUBDIRS = AuthTokenValidate ApacheSupport PamSupport AuthTokenSvc JaasSupport
|
||||
|
||||
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
|
||||
|
||||
37
CASA-auth-token/server/PamSupport/Makefile.am
Normal file
37
CASA-auth-token/server/PamSupport/Makefile.am
Normal 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
|
||||
|
||||
80
CASA-auth-token/server/PamSupport/README
Normal file
80
CASA-auth-token/server/PamSupport/README
Normal 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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
13
CASA-auth-token/server/PamSupport/TODO
Normal file
13
CASA-auth-token/server/PamSupport/TODO
Normal 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.
|
||||
110
CASA-auth-token/server/PamSupport/linux/Makefile.am
Normal file
110
CASA-auth-token/server/PamSupport/linux/Makefile.am
Normal 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
|
||||
|
||||
649
CASA-auth-token/server/PamSupport/pam_authtoken.c
Normal file
649
CASA-auth-token/server/PamSupport/pam_authtoken.c
Normal 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
|
||||
|
||||
32
CASA-auth-token/server/PamSupport/test/README
Normal file
32
CASA-auth-token/server/PamSupport/test/README
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2
CASA-auth-token/server/PamSupport/test/make.sh
Executable file
2
CASA-auth-token/server/PamSupport/test/make.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
gcc -o pamTest test.c -g -I"../../.." -I"../../../../include" -DN_PLAT_UNIX -L"../../../lib/Release" -lpam
|
||||
520
CASA-auth-token/server/PamSupport/test/test.c
Normal file
520
CASA-auth-token/server/PamSupport/test/test.c
Normal 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() --*/
|
||||
|
||||
6
CASA-auth-token/server/PamSupport/test/testservice
Normal file
6
CASA-auth-token/server/PamSupport/test/testservice
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user