The non-java project is being replaced by a client and a server project

in order to allow for the client component to be consumed by
distributions targeting the desktop. This check-in is for the server
project.
This commit is contained in:
Juan Carlos Luciani 2006-11-13 04:05:01 +00:00
parent 4f53c776c9
commit 2cc21a344c
99 changed files with 21159 additions and 0 deletions

View File

@ -0,0 +1,2 @@
Juan Carlos Luciani - jluciani@novell.com

View File

@ -0,0 +1,41 @@
#######################################################################
#
# 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 LINUX
SUBDIRS = $(TARGET_OS)
else
SUBDIRS =
endif
DIST_SUBDIRS = linux
CFILES =
EXTRA_DIST = $(CFILES)
.PHONY: package package-clean package-install package-uninstall
package package-clean package-install package-uninstall:
$(MAKE) -C $(TARGET_OS) $@
maintainer-clean-local:
rm -f Makefile.in

View File

@ -0,0 +1,132 @@
/***********************************************************************
*
* 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>
*
***********************************************************************/
/***********************************************************************
*
* 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>
The AuthName directive specifies the name of the authentication REALM relayed
by the server to HTTP clients when requesting that the they authenticate using
the Basic Authentication scheme. The AuthName can be used by the HTTP client to
realize that the server is expecting CASA Authentication Token materials.
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.

View 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.

View File

@ -0,0 +1,119 @@
#######################################################################
#
# 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
DEFINES = -DDBG
else
TARGET_CFG = Release
DEFINES = -DNDEBUG
endif
SUBDIRS =
DIST_SUBDIRS =
ROOT = ../../../..
LIBDIR = $(ROOT)/$(LIB)
APACHEINCLUDE = /usr/include/apache2
APACHELIB = /usr/lib/apache2
APRINCLUDE = /usr/include/apr-1
APRLIB = /usr/lib/apr-1
# 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$(ROOT)/include -I$(APACHEINCLUDE) -I$(APRINCLUDE)
RESOURCES =
if LIB64
DEFINES += -D_LIB64
endif
CFLAGS += -Wno-format-extra-args -fno-strict-aliasing $(INCLUDES) $(DEFINES) -D_LARGEFILE64_SOURCE
LIBS = -lpthread -lcasa_s_authtoken -lapr-1 -laprutil-1
LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) -L$(LIBDIR)/$(TARGET_CFG) -L$(APACHELIB) -L$(APRLIB) -Xlinker
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) $(LIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT)
$(OBJDIR):
[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
[ -d $(LIBDIR) ] || mkdir -p $(LIBDIR)
[ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(TARGET_CFG)
install-exec-local: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT)
$(mkinstalldirs) $(DESTDIR)$(libdir)
$(INSTALL_PROGRAM) $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(DESTDIR)$(libdir)/
uninstall-local:
cd $(DESTDIR)$(libdir); rm -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT)
rmdir $(DESTDIR)$(libdir)
#installcheck-local: install
# $(mkinstalldirs) $(DESTDIR)$(libdir)
# $(INSTALL_PROGRAM) $(DESTDIR)$(libdir)
# cd $(DESTDIR)$(libdir); $(MONO)
clean-local:
#cd $(TARGET_CFG); rm -rf *.dbg *.exe *.dll *.o *.so; cd ..; rmdir $(OBJDIR)
rm -rf $(TARGET_CFG)
distclean-local:
maintainer-clean-local:
rm -f Makefile.in

View File

@ -0,0 +1,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
};

View File

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

View File

@ -0,0 +1,41 @@
#######################################################################
#
# 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 LINUX
SUBDIRS = $(TARGET_OS) idenTokenProviders Svc
else
SUBDIRS =
endif
DIST_SUBDIRS = linux idenTokenProviders Svc
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

View File

@ -0,0 +1,99 @@
/***********************************************************************
*
* 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>
*
***********************************************************************/
/***********************************************************************
*
* 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,
libcasa_s_authtoken relies on the CasaAuthtokenValidateD service in order to perform its
functions. To learn more about CasaAuthtokenValidateD see the Svc folder.
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/CASA/authtoken/modules 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.

View File

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

View File

@ -0,0 +1,80 @@
/***********************************************************************
*
* 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>
*
***********************************************************************/
/***********************************************************************
*
* README for CasaAuthtokenValidateD
*
***********************************************************************/
INTRODUCTION
CasaAuthtokenValidateD provides a service that is utilized by libcasa_s_authtoken
for the validation of CASA Authentication Tokens.
Processes executing libcasa_s_authtoken communicate with CasaAuthTokenValidateD via
domain sockets. CasaAuthTokenValidateD validates authentication tokens by invoking
the appropriate CASA Authentication Token Java classes.
COMMAND LINE PARAMETERS
CasaAuthtokenValidateD has the following command line parameters:
-b BeginThreads
Optional parameter that specifies the initial number of threads utilized by the
service to process requests.
-g GrowThreads
Optional parameter that specifies the number of threads by which the service can
grow its thread pool utilized for processing requests.
-m MaxThreads
Optional parameter that specifies the maximum number of threads that the service
can have in its thread pool for processing requests.
-D DebugLevel
Optional parameter that specifies the level used for logging debugging information.
0 being the lowest debug level.
-d
Optional parameter that specifies that the service must be run as a daemon.
SECURITY CONSIDERATIONS
Appropriate rights need to be set on the folder used by CasaAuthtokenValidateD to
create its listeing socket to keep other services from hijacking it and taking on
the validation of CASA authentication sockets. CasaAuthtokenValidateD creates its
listen socket in the /var/lib/CASA/authtoken/validate/ folder.

View File

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

View File

@ -0,0 +1,131 @@
#!/bin/sh
#
# Startup script for the Casa Authtoken Validate Daemon (casa_atvd)
#
# /etc/init.d/casa_atvd
#
# description: casa_atvd validates CASA
# authentication tokens on behalf of native (non-java)
# services.
#
# processname: casa_atvd
# pidfile: None
# config utility: None
### BEGIN INIT INFO
# Provides: casa_atvd
# Required-Start: $local_fs $remote_fs
# X-UnitedLinux-Should-Start: $syslog $time
# Required-Stop: $local_fs $remote_fs
# X-UnitedLinux-Should-Stop: $syslog $time
# Default-Start: 1 2 3 5
# Default-Stop:
# Short-Description: Casa Authtoken Validate Daemon
# Description: Start Casa Authtoken Validate Daemon
### END INIT INFO
. /etc/rc.status
# Shell functions sourced from /etc/rc.status:
# rc_check check and set local and overall rc status
# rc_status check and set local and overall rc status
# rc_status -v ditto but be verbose in local rc status
# rc_status -v -r ditto and clear the local rc status
# rc_failed set local and overall rc status to failed
# rc_reset clear local rc status (overall remains)
# rc_exit exit appropriate to overall rc status
# First reset status of this service
rc_reset
MyStatus()
{
ps ax | grep "$DAEMON" | grep -v grep 2>&1 > /dev/null
if [ "x$?" = "x0" ]; then
RVAL=0
else
RVAL=3
fi
}
START_DAEMON_CMD=start_daemon
START_DAEMON_CMD_FLAG=-u
STATUS=MyStatus
LOG_SUCCESS=log_success_msg
LOG_FAILURE=log_failure_msg
LOG_WARNING=log_warning_msg
ECHO=
DAEMON=/usr/bin/casa_atvd
DAEMON_USER=casaatvd
StartDAEMON()
{
# Source the environments file for our daemon
. /etc/CASA/authtoken/validate/envvars
# Update the limit parameters
#
# Do not allow for unlimited core dumps if the daemon is automatically
# re-starting crashed processes.
if [ $DAEMON_NO_AUTORESTART_AFTER_CRASH ]; then
if [ $DAEMON_NO_AUTORESTART_AFTER_CRASH -ne 0 ]; then
# Feature disabled, allow core dumping.
ulimit -c unlimited
else
# Check if core dumping is allowed with the feature enabled
if [ $DAEMON_COREDUMPS_WANTED ]; then
ulimit -c unlimited
fi
fi
else
# Check if core dumping is allowed with the feature enabled
if [ $DAEMON_COREDUMPS_WANTED ]; then
ulimit -c unlimited
fi
fi
ulimit -f unlimited
# Start the daemon
echo -n "Starting casa_atvd..."
$START_DAEMON_CMD $START_DAEMON_CMD_FLAG $DAEMON_USER $DAEMON -d
RVAL=$?
$ECHO
}
StopDAEMON()
{
echo -n "Stopping casa_atvd..."
killproc $DAEMON
RVAL=$?
$ECHO
}
case "$1" in
start)
StartDAEMON
;;
stop)
StopDAEMON
;;
restart|reload|force-reload)
StopDAEMON
sleep 1
StartDAEMON
;;
status)
$STATUS
;;
*)
echo -n "Usage: $0 <start|stop|restart|reload|force-reload>" > /dev/stderr
RVAL=1
;;
esac
rc_failed $RVAL
rc_status -v
rc_exit

View File

@ -0,0 +1,122 @@
#######################################################################
#
# 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
DEFINES = -DDBG
else
TARGET_CFG = Release
DEFINES = -DNDEBUG
endif
# Override the link setting for C++
LINK = g++
SUBDIRS =
DIST_SUBDIRS =
ROOT = ../../../..
LIBDIR = $(ROOT)/$(LIB)
BINDIR = $(ROOT)/$(BIN)
JAVA_LIBDIR = /usr/lib/jvm/java-1.5.0-ibm/jre/bin
JAVA_INCDIR = /usr/lib/jvm/java-1.5.0-ibm/include
# handle Mono secondary dependencies
export MONO_PATH := $(MONO_PATH)
MODULE_NAME = CasaAuthtokenValidateD
CFILES =
CPPFILES = server.cpp
CSFILES_CSC :=
INCLUDES = -I. -I$(ROOT)/include -I$(JAVA_INCDIR)
RESOURCES =
if LIB64
DEFINES += -D_LIB64
endif
CFLAGS += -Wno-format-extra-args -fno-strict-aliasing $(INCLUDES) $(DEFINES)
CPPFLAGS += -Wno-format-extra-args -fno-strict-aliasing -fPIC $(INCLUDES) $(DEFINES) $(RPM_OPT_FLAGS)
LIBS = -lpthread -lcasa_s_ipc -ljvm -ljsig -lj9thr23
LDFLAGS = -L$(LIBDIR)/$(TARGET_CFG) -L$(JAVA_LIBDIR) -L$(JAVA_LIBDIR)/classic
OBJDIR = ./$(TARGET_CFG)/$(LIB)
OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) $(addprefix $(OBJDIR)/, $(CPPFILES:%.cpp=%.o))
EXTRA_DIST = $(CFILES) $(CPPFILES) *.h CasaAuthtokenValidateD envvars
CUR_DIR := $(shell pwd)
all: $(OBJDIR)/$(MODULE_NAME)
#
# Pattern based rules.
#
vpath %.c .
vpath %.cpp .
$(OBJDIR)/%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
$(OBJDIR)/%.o: %.cpp
$(CC) -c $(CPPFLAGS) -o $@ $<
$(OBJDIR)/$(MODULE_NAME): $(OBJDIR) $(OBJS)
@echo [======== Linking $@ ========]
$(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS)
cp -f $(OBJDIR)/$(MODULE_NAME) $(BINDIR)/$(TARGET_CFG)/$(MODULE_NAME)
$(OBJDIR):
[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
[ -d $(LIBDIR) ] || mkdir -p $(LIBDIR)
[ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(TARGET_CFG)
[ -d $(BINDIR) ] || mkdir -p $(BINDIR)
[ -d $(BINDIR)/$(TARGET_CFG) ] || mkdir -p $(BINDIR)/$(TARGET_CFG)
install-exec-local: $(OBJDIR)/$(MODULE_NAME)
$(mkinstalldirs) $(DESTDIR)$(libdir)
$(INSTALL_PROGRAM) $(OBJDIR)/$(MODULE_NAME) $(DESTDIR)$(libdir)/
uninstall-local:
cd $(DESTDIR)$(libdir); rm -f $(OBJDIR)/$(MODULE_NAME)
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

View File

@ -0,0 +1,35 @@
############################################################
# #
# Environment variable file for casa_atvd. #
# #
# Note: This file is sourced by the casa_atvd rc script #
# when starting the service. #
# #
# The following variables are utilized by the daemon #
# and its rc script: #
# #
# DAEMON_NO_AUTORESTART_AFTER_CRASH - #
# #
# Set this variable to "1" if you want to disable the #
# auto-restart daemon after abnormal termination #
# feature. This variable is intended to facilitate #
# the discovery of problems during quality assurance #
# testing. Disabling of the auto-restart daemon after #
# abnormal termination feature will result in a #
# configuration that is less fault tolerant. #
# #
# DAEMON_COREDUMPS_WANTED - #
# #
# Set this variable to allow core dumps to be taken #
# when a daemon terminates abnormally. This variable #
# is only meaningful when the auto-restart daemon #
# feature mentioned above is enabled. Core dumps are #
# allowed to be taken when the auto-restart daemon #
# feature is disabled. Core dumps of novell-xsrvd #
# service processes are taken to the #
# /var/novell/xtier folder. #
# #
############################################################
LD_LIBRARY_PATH="\${LD_LIBRARY_PATH}":/usr/lib/jvm/java-1.5.0-ibm/jre/bin:/usr/lib/jvm/java-1.5.0-ibm/jre/bin/classic
export LD_LIBRARY_PATH

View File

@ -0,0 +1,148 @@
/**********************\*************************************************
*
* 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 _IPCINT_
#define _IPCINT_
//===[ Include files ]=====================================================
#include <iostream>
#include <string>
#include <list>
#include <map>
#include <vector>
using namespace std;
extern "C" {
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <syslog.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <assert.h> // Ensure that NDEBUG is defined for release builds!
#include <sys/ipc.h>
#include <casa_s_ipc.h>
}
//===[ External data ]=====================================================
extern int DebugLevel;
extern bool UseSyslog;
extern char appName[];
extern char *pAppName;
extern pthread_mutex_t interlockedMutex;
//===[ Macro definitions ]=================================================
//
// DbgTrace macro define
//
#define MAX_FORMAT_STRING_LEN 1024
#define DbgTrace(LEVEL, X, Y) { \
if (LEVEL == 0 || DebugLevel >= LEVEL) { \
if (UseSyslog) \
syslog(LOG_USER | LOG_INFO, X, Y); \
else { \
char *pFormatString = new char[MAX_FORMAT_STRING_LEN]; \
if (pFormatString) { \
snprintf(pFormatString, MAX_FORMAT_STRING_LEN, X, Y); \
fprintf(stderr, "%s -%s", appName, pFormatString); \
delete[] pFormatString; \
} \
} \
} \
}
//
// Interlocked Increment and Decrement macros
//
// Well, kind of interlocked :-).
//
__inline static unsigned long
InterlockedIncrement(unsigned long *pValue)
{
unsigned long retVal;
pthread_mutex_lock(&interlockedMutex);
(*pValue) ++;
retVal = *pValue;
pthread_mutex_unlock(&interlockedMutex);
return retVal;
}
__inline static unsigned long
InterlockedDecrement(unsigned long *pValue)
{
unsigned long retVal;
pthread_mutex_lock(&interlockedMutex);
(*pValue) --;
retVal = *pValue;
pthread_mutex_unlock(&interlockedMutex);
return retVal;
}
__inline static uint32_t
InterlockedIncrement(uint32_t *pValue)
{
uint32_t retVal;
pthread_mutex_lock(&interlockedMutex);
(*pValue) ++;
retVal = *pValue;
pthread_mutex_unlock(&interlockedMutex);
return retVal;
}
__inline static uint32_t
InterlockedDecrement(uint32_t *pValue)
{
uint32_t retVal;
pthread_mutex_lock(&interlockedMutex);
(*pValue) --;
retVal = *pValue;
pthread_mutex_unlock(&interlockedMutex);
return retVal;
}
//===[ Include files ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
#endif // _IPCINT_
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,839 @@
/***********************************************************************
*
* 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"
#include <jni.h>
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
#define MAXFD 64
#define DOMAIN_SOCKET_FILE_NAME "/var/lib/CASA/authtoken/validate/socket"
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
void*
WorkerThread(void*);
//===[ Global variables ]==================================================
// Usage string
char usage[] = "\nCasaAuthtokenValidateD: usage: [-p ListenPort] [-b BeginThreads] [-g GrowThreads] [-m MaxThreads] [-D DebugLevel] [-d]\n";
// Worker thread pool configuration parameters
int beginThreads = 5;
int growThreads = 5;
int maxThreads = 4096;
int minWaitingThreads = beginThreads;
int maxWaitingThreads = beginThreads * 4;
// Worker thread pool operating parameters
double numThreads = 0;
double numBusyThreads = 0;
double numPerishingThreads = 0;
// Listen Port Number
//int listenPortNumber = 5000;
int listenPortNumber = 0;
// Parameter indicating whether or not the server needs to run
// as a daemon.
bool daemonize = false;
// Name to use for logging purposes
char appName[] = "CasaAuthtokenValidateD";
// Debug Level
int DebugLevel = 0;
bool UseSyslog = false;
// Variables for daemon auto-restart after crash feature
static bool autoRestartAfterCrash = true;
// Synchronization variables
pthread_mutex_t interlockedMutex;
pthread_mutex_t serverMutex;
pthread_cond_t serverCondition;
// Operating parameters
bool terminating = false;
// Java parameters
JavaVM *g_jvm = NULL;
JNIEnv *g_env = NULL;
char classpath[] = "-Djava.class.path=/usr/share/java/CASA/authtoken/CasaAuthToken.jar:/usr/share/java/CASA/authtoken/external/axis.jar:/usr/share/java/CASA/authtoken/external/axis-ant.jar:/usr/share/java/CASA/authtoken/external/commons-discovery-0.2.jar:/usr/share/java/CASA/authtoken/external/commons-logging-1.0.4.jar:/usr/share/java/CASA/authtoken/external/jaxrpc.jar:/usr/share/java/CASA/authtoken/external/log4j-1.2.8.jar:/usr/share/java/CASA/authtoken/external/saaj.jar:/usr/share/java/CASA/authtoken/external/wsdl4j-1.5.1.jar:/usr/share/java/CASA/authtoken/external/wss4j-1.5.0.jar:/usr/share/java/CASA/authtoken/external/xalan.jar:/usr/share/java/CASA/authtoken/external/xercesImpl.jar:/usr/share/java/CASA/authtoken/external/xml-apis.jar:/usr/share/java/CASA/authtoken/external/xmlsec-1.2.1.jar:/usr/share/java/CASA/authtoken/external:/etc/CASA/authtoken/keys/client";
// Java AuthenticationToken Class and method name
//char authTokenClassName[] = "jtest";
//char authTokenClassValidateMethodName[] = "test4";
char authTokenClassName[] = "com/novell/casa/authtoksvc/AuthToken";
char authTokenClassValidateMethodName[] = "validate";
//++=======================================================================
void
GrowWorkerThreadPool(int growNumber)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes: The serverMutex needs to be held when calling this
// procedure.
//
// L2
//=======================================================================--
{
DbgTrace(1, "GrowWorkerThreadPool- Start\n", 0);
for (int i = 0; i < growNumber; i++)
{
int threadCreateStatus;
pthread_t thread;
if ((threadCreateStatus = pthread_create(&thread,
NULL,
(void*(*)(void*))WorkerThread,
NULL) == 0))
{
// Worker thread created
numThreads ++;
}
else
{
DbgTrace(0, "GrowWorkerThreadPool- Thread creation failed, status = %0d\n", threadCreateStatus);
}
}
// Let our server know if we ended up with no worker threads
if (numThreads == 0)
pthread_cond_signal(&serverCondition);
DbgTrace(1, "GrowWorkerThreadPool- End\n", 0);
} /*-- GrowWorkerThreadPool() --*/
//++=======================================================================
void
WorkerThreadBusy(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "WorkerThreadBusy- Start\n", 0);
// Acquire our mutex
pthread_mutex_lock(&serverMutex);
// Increment the numBusyThread count and grow the number of worker threads
// if necessary.
numBusyThreads ++;
if ((numThreads - numBusyThreads) < minWaitingThreads)
GrowWorkerThreadPool(growThreads);
// Release our mutex
pthread_mutex_unlock(&serverMutex);
DbgTrace(1, "WorkerThreadBusy- End\n", 0);
} /*-- WorkerThreadBusy() --*/
//++=======================================================================
bool
WorkerThreadWaiting(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
bool retValue;
DbgTrace(1, "WorkerThreadWaiting- Start\n", 0);
// Acquire our mutex
pthread_mutex_lock(&serverMutex);
// Decrement the numBusyThread count
numBusyThreads --;
// Check if we have too many idle workers
if ((numThreads - numBusyThreads - numPerishingThreads) > maxWaitingThreads
&& numThreads > beginThreads)
{
// We want to let this worker perish
numPerishingThreads ++;
retValue = true;
}
else
retValue = false;
// Release our mutex
pthread_mutex_unlock(&serverMutex);
DbgTrace(1, "WorkerThreadWaiting- End, retValue = %X\n", retValue);
return retValue;
} /*-- WorkerThreadWaiting() --*/
//++=======================================================================
void*
WorkerThread(void*)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
bool perishingThread = false;
DbgTrace(1, "WorkerThread- Start\n", 0);
// Set the thread in the detached state so that it is cleaned up when it exits
pthread_detach(pthread_self());
// Attach the thread to the JVM
JNIEnv *env;
JavaVMAttachArgs attachArgs = {0};
attachArgs.version = JNI_VERSION_1_4;
if (g_jvm->AttachCurrentThread((void**) &env, &attachArgs) >= 0)
{
// We are now attached to the JVM, find the helper class that
// we need.
jclass helperClass = env->FindClass(authTokenClassName);
if (helperClass)
{
// Helper class found, now get the id of the method that we invoke
jmethodID mId = env->GetStaticMethodID(helperClass,
authTokenClassValidateMethodName,
"(Ljava/lang/String;)Ljava/lang/String;");
if (mId)
{
// Loop until told to terminate
while (!terminating)
{
// Get a request that needs servicing
int32_t requestId = IpcServerGetRequest();
if (requestId != 0)
{
// We got a request that needs servicing, now get the
// data associated with it.
char *pReqData;
int dataLen = IpcServerGetRequestData(requestId, &pReqData);
if (dataLen != 0)
{
// Indicate that we are now busy
WorkerThreadBusy();
// Lets push the jvm local frame to allow us to clean up our local
// references later.
env->PushLocalFrame(10);
// Encapsulate the request data into a string object
jstring inString = env->NewStringUTF(pReqData);
if (inString)
{
// Invoke our helper method
jstring outString = (jstring) env->CallStaticObjectMethod(helperClass, mId, inString);
// Check if an excption occurred
if (env->ExceptionCheck() == JNI_TRUE)
{
// There is a pending exception, display the info which in turn clears it.
env->ExceptionDescribe();
}
else
{
if (outString)
{
// The helper method succeded, complete the request
// with the data returned.
const char *pOutChars = env->GetStringUTFChars(outString, NULL);
if (pOutChars)
{
IpcServerCompleteRequest(requestId, (char*) pOutChars);
env->ReleaseStringUTFChars(outString, pOutChars);
}
else
{
DbgTrace(0, "WorkerThread- Unable to get UTF characters\n", 0);
IpcServerAbortRequest(requestId);
}
}
else
{
// The helper method failed, just abort the request.
IpcServerAbortRequest(requestId);
}
}
}
else
{
DbgTrace(0, "WorkerThread- UTF String allocation failure\n", 0);
IpcServerAbortRequest(requestId);
}
// Pop the jvm local frame to clean up our local references
env->PopLocalFrame(NULL);
// Indicate that we are no longer busy and get indication of
// whether or not we should continue to try to process requests.
if (WorkerThreadWaiting() == true)
{
DbgTrace(1, "WorkerThread- Requested to terminate\n", 0);
// Remember that we are a perishing thread so that we can reduce the
// count as we exit.
perishingThread = true;
break;
}
}
else
{
DbgTrace(0, "WorkerThread- Error obtaining Request data\n", 0);
IpcServerAbortRequest(requestId);
}
}
else
{
// No need to service requests any longer
break;
}
}
}
else
{
DbgTrace(0, "WorkerThread- Failed to get method id\n", 0);
}
}
else
{
DbgTrace(0, "WorkerThread- Failed to find helper class\n", 0);
}
// Detach from the JVM
g_jvm->DetachCurrentThread();
}
else
{
DbgTrace(0, "WorkerThread- Failed to attach to JVM\n", 0);
}
// Decrement the number of worker threads and signal our main thread
// to terminate itself if we are the last worker thread.
pthread_mutex_lock(&serverMutex);
if (perishingThread)
numPerishingThreads --;
numThreads --;
if (numThreads == 0)
pthread_cond_signal(&serverCondition);
pthread_mutex_unlock(&serverMutex);
DbgTrace(1, "WorkerThread- End\n", 0);
// Exit
pthread_exit(NULL);
return 0; // never-reached!
} /*-- WorkerThread() --*/
//++=======================================================================
void
SigTermHandler(
int signum)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "SigTermHandler- Start\n", 0);
// Indicate that we are terminating
terminating = true;
// Shutdown the IPC Server
IpcServerShutdown();
DbgTrace(1, "SigTermHandler- End\n", 0);
} /*-- SigTermHandler() --*/
//++=======================================================================
int
InitJavaInvoke(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "InitJavaInvoke- Start\n", 0);
JavaVMOption options[6];
options[0].optionString = classpath;
options[1].optionString = "-Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser";
options[2].optionString = "-Djavax.xml.parsers.DocumentBuilderFactory=org.apache.xerces.jaxp.DocumentBuilderFactoryImpl";
options[3].optionString = "-Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp.SAXParserFactoryImpl";
//options[4].optionString = "-Xcheck:jni";
//options[5].optionString = "-Djaxp.debug=1";
JavaVMInitArgs vm_args;
vm_args.version = JNI_VERSION_1_4;
vm_args.options = options;
vm_args.nOptions = 4;
vm_args.ignoreUnrecognized = true;
if (JNI_CreateJavaVM(&g_jvm, (void**)&g_env, &vm_args) >= 0)
{
// Success
retStatus = 0;
}
else
{
DbgTrace(0, "InitJavaInvoke- Error creating Java VM\n", 0);
}
DbgTrace(1, "InitJavaInvoke- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- InitJavaInvoke() --*/
//++=======================================================================
void
UnInitJavaInvoke(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "UnInitJavaInvoke- Start\n", 0);
// Destroy the jvm
g_jvm->DestroyJavaVM();
g_jvm = NULL;
g_env = NULL;
DbgTrace(1, "UnInitJavaInvoke- End\n", 0);
} /*-- UnInitJavaInvoke() --*/
//++=======================================================================
void
DaemonInit(
const char *pname)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes: Copy of daemon_init() in Richard Stevens Unix Network
// Programming Book.
//
// L2
//=======================================================================--
{
pid_t pid;
char *pNoAutoRestartEnvvar;
DbgTrace(1, "DaemonInit- Start\n", 0);
// Determine if we need to disable the auto-restart after crash feature
if ((pNoAutoRestartEnvvar = getenv("CASA_NO_AUTORESTART_AFTER_CRASH")) != NULL
&& strcmp(pNoAutoRestartEnvvar, "0") != 0)
{
DbgTrace(1, "DaemonInit- Disabling daemon auto-restart after crash feature\n", 0);
autoRestartAfterCrash = false;
}
// Fork to run in the background, check for error.
if ((pid = fork()) == -1)
{
DbgTrace(0, "DaemonInit- Fork error = %d\n", errno);
exit(0);
}
else if (pid != 0)
{
// The fork succeeded and we are the parent process, terminate
// ourselves.
exit(0);
}
/* 1st child continues */
// Become the session leader and set to ignore SIGHUP
setsid();
signal(SIGHUP, SIG_IGN);
// Fork again to guarantee that the daemon can not acquire a
// controlling terminal.
if ((pid = fork()) == -1)
{
DbgTrace(0, "DaemonInit- Fork error = %d\n", errno);
exit(0);
}
else if (pid != 0)
{
// The fork succeeded and we are the parent process, terminate
// ourselves.
exit(0);
}
/* 2nd child continues */
// Close any open descriptors
for (int i = 0; i < MAXFD; i++)
close(i);
// Spawn a worker
if ((pid = fork()) == -1)
{
DbgTrace(0, "DaemonInit- Fork error = %d\n", errno);
exit(0);
}
else if (pid == 0)
{
// The fork succeeded and we are the worker, continue.
}
else
{
// We are the parent of the server, check if we must execute the auto-restart
// server after crash logic.
if (autoRestartAfterCrash)
{
// Execute auto-restart server after crash logic
while (1)
{
int childExitStatus;
// Wait for children to exit
pid = wait(&childExitStatus);
if (pid != -1)
{
// Fork worker
if ((pid = fork()) == -1)
{
DbgTrace(0, "DaemonInit- Fork error = %d\n", errno);
exit(0);
}
else if (pid == 0)
{
// The fork succeeded and we are the server, exit the loop
// to start.
goto childContinue;
}
// We are the parent process, continue to watch for a terminated child process.
syslog(LOG_USER | LOG_INFO, "CasaAuthtokenValidateD: Worker re-started after it terminated unexpectedly");
sleep(1); // To keep from consuming too many cycles
}
else
{
// Check if we must exit the loop
if (errno != EINTR)
break;
}
}
}
// Terminate ourselves.
exit(0);
}
childContinue:
// Set flag to inform DbgTrace macros to use Syslog
UseSyslog = true;
// Change the working directory
chdir("/var/lib/CASA/authtoken/validate");
// Clear our file mode creation mask
umask(0);
// Get ready to log
openlog(appName, LOG_CONS | LOG_NOWAIT | LOG_ODELAY| LOG_PID, LOG_USER);
if (DebugLevel == 0)
setlogmask(LOG_UPTO(LOG_INFO));
else
setlogmask(LOG_UPTO(LOG_DEBUG));
DbgTrace(1, "DaemonInit- End\n", 0);
} /*-- DaemonInit() --*/
//++=======================================================================
int
main(
int argc,
char* argv[])
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int optionsSpecified = 0;
bool doneScanning = false;
bool invalidOption = false;
int option;
//printf("**** AuthTokenValidate Daemon ****\n");
// Scan through the options specified
while (!doneScanning)
{
opterr = 0;
option = getopt(argc, argv, "m:p:b:g:D:d");
// Proceed based on the result
switch (option)
{
case 'p':
// Port number option, record location of
// argument.
listenPortNumber = atoi(optarg);
optionsSpecified ++;
break;
case 'b':
// Begin threads option, override the default parameter
// with the value of the option.
beginThreads = atoi(optarg);
optionsSpecified ++;
break;
case 'g':
// Grow threads option, override the default parameter
// with the value of the option.
growThreads = atoi(optarg);
optionsSpecified ++;
break;
case 'm':
// Max threads option, override the default parameter
// with the value of the option.
maxThreads = atoi(optarg);
optionsSpecified ++;
break;
case 'd':
// Run as daemon option
daemonize = true;
optionsSpecified ++;
break;
case 'D':
// Set the debug level
DebugLevel = atoi(optarg);
optionsSpecified++;
break;
case '?':
// Invalid option detected
doneScanning = true;
invalidOption = true;
break;
default:
// Done scanning
doneScanning = true;
break;
}
}
// Do some sanity checking
if (!invalidOption
&& beginThreads > 0
&& maxThreads > (growThreads+beginThreads)
&& beginThreads <= maxThreads)
{
// The server is ready to start, check if we must
// run it as a daemon.
if (daemonize)
DaemonInit(argv[0]);
// Set a handler for SIGTERM
signal(SIGTERM, SigTermHandler);
// Initialize our mutexes
pthread_mutex_init(&interlockedMutex, NULL);
pthread_mutex_init(&serverMutex, NULL);
// Initialize the JVM
if (InitJavaInvoke() == 0)
{
// Initialize the condition that we will use to wait
// for the exit of all of our worker threads.
if (pthread_cond_init(&serverCondition, NULL) == 0)
{
// Initialize the IPC Server
if (IpcServerInit(appName,
DebugLevel,
UseSyslog) == 0)
{
// Now setup the appropriate listen address
int setAddressResult;
if (listenPortNumber == 0)
setAddressResult = IpcServerSetUnAddress(DOMAIN_SOCKET_FILE_NAME);
else
setAddressResult = IpcServerSetInAddress(listenPortNumber);
if (setAddressResult == 0)
{
// Now start the IPC server
if (IpcServerStart() == 0)
{
// Acquire our mutex
pthread_mutex_lock(&serverMutex);
// Start worker threads
GrowWorkerThreadPool(beginThreads);
// Wait for the worker threads to terminate
pthread_cond_wait(&serverCondition, &serverMutex);
// Release our mutex
pthread_mutex_unlock(&serverMutex);
DbgTrace(0, "main- Exiting, numThreads = %d\n", numThreads);
}
}
else
{
DbgTrace(0, "main- Setting of listen address failed\n", 0);
}
}
else
{
DbgTrace(0, "main- Initialization of Ipc server failed\n", 0);
}
}
else
{
DbgTrace(0, "main- Condition initialization failed\n", 0);
}
// Un-initialize JVM
UnInitJavaInvoke();
}
else
{
DbgTrace(0, "main- JVM initialization failed\n", 0);
}
}
else
{
// Invalid option detected or the user failed to
// specify the listening port number.
printf(usage, argv[0]);
}
return 0;
} /*-- main() --*/
//=========================================================================
//=========================================================================

View File

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

View 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);
}
//++=======================================================================
//++=======================================================================
//++=======================================================================

View 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_

View File

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

View File

@ -0,0 +1,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

View File

@ -0,0 +1,62 @@
/***********************************************************************
*
* 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>
*
***********************************************************************/
/***********************************************************************
*
* 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/CASA/authtoken/modules 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.

View File

@ -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

View File

@ -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;
}
//++=======================================================================
//++=======================================================================
//++=======================================================================

View File

@ -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_

View File

@ -0,0 +1,15 @@
#######################################################
# #
# CASA Authentication Token System configuration file #
# for module: #
# #
# CasaIdentityToken #
# #
# Note: This module is the provider of Casa Identity #
# tokens. #
# #
#######################################################
LibraryName /usr/lib/CASA/authtoken/casa_iden_token.so

View File

@ -0,0 +1,15 @@
#######################################################
# #
# CASA Authentication Token System configuration file #
# for module: #
# #
# CasaIdentityToken #
# #
# Note: This module is the provider of Casa Identity #
# tokens. #
# #
#######################################################
LibraryName /usr/lib64/CASA/authtoken/casa_iden_token.so

View File

@ -0,0 +1,125 @@
#######################################################################
#
# 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
DEFINES = -DDBG
else
TARGET_CFG = Release
DEFINES = -DNDEBUG
endif
SUBDIRS =
DIST_SUBDIRS =
ROOT = ../../../../..
CASAINCLUDE = ../../../../../../CASA/include
LIBDIR = $(ROOT)/$(LIB)
# handle Mono secondary dependencies
export MONO_PATH := $(MONO_PATH)
PLATFORMINDEPENDENTSOURCEDIR = ..
PLATFORMDEPENDENTSOURCEDIR = .
MODULE_NAME = casa_iden_token
MODULE_EXT = so
CFILES = ../identokenprovider.c \
../identoken.c \
../util.c \
platform.c
CSFILES_CSC :=
INCLUDES = -I. -I.. -I../../.. -I$(CASAINCLUDE) -I../../../../../include
RESOURCES =
DEST_CONF_FILE_NAME = CasaIdentityToken.conf
if LIB64
DEFINES += -D_LIB64
SRC_CONF_FILE_NAME = CasaIdentityToken_lib64.conf
else
SRC_CONF_FILE_NAME = CasaIdentityToken.conf
endif
CFLAGS += -Wno-format-extra-args -fno-strict-aliasing $(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 CasaIdentityToken.conf CasaIdentityToken_lib64.conf
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) $(LIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT)
cp -f $(SRC_CONF_FILE_NAME) $(LIBDIR)/$(TARGET_CFG)/$(DEST_CONF_FILE_NAME)
$(OBJDIR):
[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
[ -d $(LIBDIR) ] || mkdir -p $(LIBDIR)
[ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(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

View File

@ -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);
}
//++=======================================================================
//++=======================================================================
//++=======================================================================

View File

@ -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 ]===============================================
//=========================================================================

View 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:
//
// 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;
}
//++=======================================================================
//++=======================================================================
//++=======================================================================

View File

@ -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_

View 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/CASA/authtoken/modules",
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);
}
//++=======================================================================
//++=======================================================================
//++=======================================================================

View File

@ -0,0 +1,224 @@
/***********************************************************************
*
* 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 <casa_c_ipc.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;
extern char IpcClientLibraryPath[];
//===[ 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_

View File

@ -0,0 +1,121 @@
#######################################################################
#
# 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
DEFINES = -DDBG
else
TARGET_CFG = Release
DEFINES = -DNDEBUG
endif
SUBDIRS =
DIST_SUBDIRS =
ROOT = ../../..
CASAINCLUDE = ../../../../CASA/include
LIBDIR = $(ROOT)/$(LIB)
# handle Mono secondary dependencies
export MONO_PATH := $(MONO_PATH)
PLATFORMINDEPENDENTSOURCEDIR = ..
PLATFORMDEPENDENTSOURCEDIR = .
MODULE_NAME = libcasa_s_authtoken
MODULE_EXT = so
CFILES = ../config.c \
../principal.c \
../util.c \
../validate.c \
../identoken.c \
platform.c
CSFILES_CSC :=
INCLUDES = -I. -I.. -I$(CASAINCLUDE) -I../../../include
RESOURCES =
if LIB64
DEFINES += -D_LIB64
endif
CFLAGS += -Wno-format-extra-args -fno-strict-aliasing $(INCLUDES) $(DEFINES)
LIBS = -lpthread -ldl
LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) -L$(ROOT)/lib/$(TARGET_CFG)
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) $(LIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT)
$(OBJDIR):
[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
[ -d $(LIBDIR) ] || mkdir -p $(LIBDIR)
[ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(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

View File

@ -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>
*
***********************************************************************/
//===[ 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;
//
// Ipc client library path
//
#ifdef _LIB64
char IpcClientLibraryPath[] = "/usr/lib64/libcasa_c_ipc.so";
#else
char IpcClientLibraryPath[] = "/usr/lib/libcasa_c_ipc.so";
#endif
//++=======================================================================
HANDLE
PlatAllocMutex(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
// L2
//=======================================================================--
{
PlatformMutex *pPlatMutex;
pthread_mutexattr_t mutexAttr;
DbgTrace(2, "-PlatAllocMutex- Start\n", 0);
// Allocate space for our mutex structure
pPlatMutex = malloc(sizeof(*pPlatMutex));
if (pPlatMutex)
{
// Finish initializing the mutex
if (pthread_mutexattr_init(&mutexAttr) == 0)
{
if (pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE) == 0)
{
if (pthread_mutex_init(&pPlatMutex->mutex, &mutexAttr) != 0)
{
DbgTrace(0, "-PlatAllocMutex- Error %d initing mutex\n", errno);
free(pPlatMutex);
pPlatMutex = NULL;
}
}
else
{
DbgTrace(0, "-PlatAllocMutex- Error %d setting mutex type\n", errno);
free(pPlatMutex);
pPlatMutex = NULL;
}
}
else
{
DbgTrace(0, "-PlatAllocMutex- Error %d initing mutexattr\n", errno);
free(pPlatMutex);
pPlatMutex = NULL;
}
}
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 = %s\n", dlerror());
}
DbgTrace(1, "-OpenLibrary- End, handle = %0lX\n", (long) 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 = %s\n", dlerror());
}
DbgTrace(1, "-GetFunctionPtr- End, pFuncPtr = %0lX\n", (long) pFuncPtr);
return pFuncPtr;
}
//++=======================================================================
//++=======================================================================
//++=======================================================================

View File

@ -0,0 +1,102 @@
/***********************************************************************
*
* 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 ]===============================================
//=========================================================================

View 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);
}
//++=======================================================================
//++=======================================================================
//++=======================================================================

View 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;
}
//++=======================================================================
//++=======================================================================
//++=======================================================================

View File

@ -0,0 +1,400 @@
/***********************************************************************
*
* 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"
//===[ Manifest constants ]================================================
#define APPLICATION_NOT_MULTI_THREADED "CASA_APPLICATION_NOT_MULTI_THREADED"
#define DOMAIN_SOCKET_FILE_NAME "/var/lib/CASA/authtoken/validate/socket"
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
// Debug Level
int DebugLevel = 0;
//
// Initialization variables
//
static
bool g_moduleInitialized = false;
//
// Configuration variables
//
bool g_multiThreadedApplication = true;
//
// IPC Client Sub-system variables
//
PFN_IpcClientInit g_ipcInitPtr = NULL;
PFN_IpcClientShutdown g_ipcShutdownPtr = NULL;
//PFN_IpcClientOpenInetRemoteEndPoint g_ipcOpenEndPointPtr = NULL;
PFN_IpcClientOpenUnixRemoteEndPoint g_ipcOpenEndPointPtr = NULL;
PFN_IpcClientCloseRemoteEndPoint g_ipcCloseEndPointPtr = NULL;
PFN_IpcClientSubmitReq g_ipcSubmitReq = NULL;
uint32_t g_atvsEndPointHandle; // Authentication Token Validation Service endpoint handle
//++=======================================================================
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))
{
// Initialize the Client Ipc Subsystem
//
// First load the library. We load it itself to keep the system
// from unloading it in-case that the application unloads us. Some
// applications such as PAM application will repeateadly load and
// unload us.
void* libHandle = OpenLibrary(IpcClientLibraryPath);
if (libHandle)
{
// The Ipc library has been loaded, now get the symbols that we need.
g_ipcInitPtr = GetFunctionPtr(libHandle, "IpcClientInit");
g_ipcShutdownPtr = GetFunctionPtr(libHandle, "IpcClientShutdown");
//g_ipcOpenEndPointPtr = GetFunctionPtr(libHandle, "IpcClientOpenInetRemoteEndPoint");
g_ipcOpenEndPointPtr = GetFunctionPtr(libHandle, "IpcClientOpenUnixRemoteEndPoint");
g_ipcCloseEndPointPtr = GetFunctionPtr(libHandle, "IpcClientCloseRemoteEndPoint");
g_ipcSubmitReq = GetFunctionPtr(libHandle, "IpcClientSubmitReq");
if (g_ipcInitPtr == NULL
|| g_ipcShutdownPtr == NULL
|| g_ipcOpenEndPointPtr == NULL
|| g_ipcCloseEndPointPtr == NULL
|| g_ipcSubmitReq == NULL)
{
DbgTrace(0, "-ValidateAuthToken- Failed to get needed Ipc library function pointer\n", 0);
IdenTokenUninit();
PrincipalIfUninit();
ConfigIfUninit();
}
else
{
if ((g_ipcInitPtr)("CASA_AuthTokenValidate",
g_multiThreadedApplication,
DebugLevel,
false) == 0)
{
// Open endpoint for the Authentication Token Validation Service
//if ((g_ipcOpenEndPointPtr)(5000,
// 0x7F000001,
// 0,
// &g_atvsEndPointHandle) == 0)
if ((g_ipcOpenEndPointPtr)(DOMAIN_SOCKET_FILE_NAME,
0,
&g_atvsEndPointHandle) == 0)
{
// Success
g_moduleInitialized = true;
}
else
{
DbgTrace(0, "-ValidateAuthToken- Failed to open remote endpoint\n", 0);
(g_ipcShutdownPtr)();
IdenTokenUninit();
PrincipalIfUninit();
ConfigIfUninit();
}
}
else
{
DbgTrace(0, "-ValidateAuthToken- Ipc subsystem initialization failed\n", 0);
(g_ipcShutdownPtr)();
IdenTokenUninit();
PrincipalIfUninit();
ConfigIfUninit();
}
}
}
else
{
DbgTrace(0, "-ValidateAuthToken- Failed to load Ipc library, error = %s\n", dlerror());
}
}
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))
{
char *pIdenTokenData;
int idenTokenDataLen;
// Assume failure
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_AUTHENTICATION_FAILURE);
// Token was decoded successfully, now submit the authentication token to the
// authentication token validation service.
if ((g_ipcSubmitReq)(g_atvsEndPointHandle,
pDecodedTokenBuf,
decodedTokenBufLen,
&pIdenTokenData,
&idenTokenDataLen) == 0)
{
// The submit succeeded, make sure that we got some identity data back.
if (pIdenTokenData)
{
if (idenTokenDataLen != 0)
{
IdenTokenProviderIf *pIdenTokenProviderIf;
// The authentication token was validated, now obtain
// Identity Token Provider interface.
retStatus = GetIdenTokenProviderInterface("CasaIdentityToken", // tbd - Hard code until we enhance the protocol with the atvs to also return this information.
&pIdenTokenProviderIf);
if (CASA_SUCCESS(retStatus))
{
IdenTokenIf *pIdenTokenIf;
// Use the Identity Token Provider to get an Identity Token Interface instance
retStatus = pIdenTokenProviderIf->getIdentityTokenIf(pIdenTokenProviderIf,
pIdenTokenData,
idenTokenDataLen,
&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);
}
}
else
{
DbgTrace(0, "-ValidateAuthToken- ValidateAuthToken submit did not return identity token data\n", 0);
}
// Free the buffer containing the identity token data
free(pIdenTokenData);
}
else
{
DbgTrace(0, "-ValidateAuthToken- ValidateAuthToken submit did not return identity token data buffer\n", 0);
}
}
else
{
DbgTrace(1, "-ValidateAuthToken- ValidateAuthToken submit failed\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;
}
//++=======================================================================
static void __attribute__((constructor))
so_init()
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Library initialization routine.
//
// L2
//=======================================================================--
{
// Check for environment variable specifying that the application is
// multi-threaded.
if (getenv(APPLICATION_NOT_MULTI_THREADED) != NULL)
{
// The parameter has been configured, remember it.
g_multiThreadedApplication = false;
}
}
//++=======================================================================
static void __attribute__((destructor))
so_fini()
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Library un-initialization routine.
//
// L2
//=======================================================================--
{
if (g_ipcShutdownPtr)
(g_ipcShutdownPtr)();
}
//++=======================================================================
//++=======================================================================
//++=======================================================================

View File

@ -0,0 +1,459 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS

View File

View File

@ -0,0 +1,41 @@
#######################################################################
#
# 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 = utilities AuthTokenValidate ApacheSupport PamSupport package
DIST_SUBDIRS = include utilities AuthTokenValidate ApacheSupport PamSupport package
EXTRA_DIST = autogen.sh
.PHONY: package package-clean package-install package-uninstall
package package-clean package-install package-uninstall:
$(MAKE) -C package $@
clean-local:
if [ -d lib ]; then rm -rf lib; fi
if [ -d bin ]; then rm -rf bin; fi
if [ -d lib64 ]; then rm -rf lib64; fi
if [ -d bin64 ]; then rm -rf bin64; fi
maintainer-clean-local:
rm -f Makefile.in

View File

View File

@ -0,0 +1,41 @@
#######################################################################
#
# 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 LINUX
SUBDIRS = $(TARGET_OS)
else
SUBDIRS =
endif
DIST_SUBDIRS = linux
CFILES =
EXTRA_DIST = $(CFILES)
.PHONY: package package-clean package-install package-uninstall
package package-clean package-install package-uninstall:
$(MAKE) -C $(TARGET_OS) $@
maintainer-clean-local:
rm -f Makefile.in

View File

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

View File

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

View File

@ -0,0 +1,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
DEFINES = -DDBG
else
TARGET_CFG = Release
DEFINES = -DNDEBUG
endif
CFLAGS += -Wno-format-extra-args -fno-strict-aliasing
SUBDIRS =
DIST_SUBDIRS =
ROOT = ../../..
CASAINCLUDE = ../../../../CASA/include
LIBDIR = $(ROOT)/$(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$(CASAINCLUDE) -I../../../include
RESOURCES =
CFLAGS += $(INCLUDES) $(DEFINES)
LIBS = -lpthread -lpam -lcasa_s_authtoken
LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT) -L$(LIBDIR)/$(TARGET_CFG)
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) $(LIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT)
$(OBJDIR):
[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
[ -d $(LIBDIR) ] || mkdir -p $(LIBDIR)
[ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(TARGET_CFG)
install-exec-local: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT)
$(mkinstalldirs) $(DESTDIR)$(libdir)
$(INSTALL_PROGRAM) $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(DESTDIR)$(libdir)/
uninstall-local:
cd $(DESTDIR)$(libdir); rm -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT)
rmdir $(DESTDIR)$(libdir)
#installcheck-local: install
# $(mkinstalldirs) $(DESTDIR)$(libdir)
# $(INSTALL_PROGRAM) $(DESTDIR)$(libdir)
# cd $(DESTDIR)$(libdir); $(MONO)
clean-local:
#cd $(TARGET_CFG); rm -rf *.dbg *.exe *.dll *.o *.so; cd ..; rmdir $(OBJDIR)
rm -rf $(TARGET_CFG)
distclean-local:
maintainer-clean-local:
rm -f Makefile.in

View File

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

View File

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

View File

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

View File

@ -0,0 +1,520 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
//===[ Include files ]=====================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <getopt.h>
#include <errno.h>
#include <security/pam_appl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
//===[ Type definitions ]==================================================
typedef struct _AppUserData
{
char *pUserName;
char *pAuthToken;
} AppUserData, *PAppUserData;
//
// DbgTrace macro define
//
#define DbgTrace(LEVEL, X, Y) { \
if (LEVEL == 0) \
printf(X, Y); \
else if (DebugLevel >= LEVEL) \
printf(X, Y); \
}
//
// Socket Mapping definitions
//
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define LINGER struct linger
#define SOCKADDR_IN struct sockaddr_in
#define closesocket close
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
// Usage string
char usage[] = "\nPamTest: usage: -s serviceName [-D DebugLevel]\n";
// Debug Level
int DebugLevel = 3;
char *pServiceName = NULL;
//++=======================================================================
int
Converse(int num_msg,
const struct pam_message **msg,
struct pam_response **resp,
void *appdata_ptr)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
int retStatus = PAM_SUCCESS;
int replies = 0;
struct pam_response *reply = NULL;
AppUserData *pAppUserData = (PAppUserData) appdata_ptr;
// Initialize output parameters
*resp = NULL;
// Check input parameters
if (num_msg <= 0 || appdata_ptr == NULL)
return PAM_CONV_ERR;
// Allocate enough space for the replies
reply = malloc(sizeof(struct pam_response) * num_msg);
if (!reply)
return PAM_CONV_ERR;
// Zero the reply buffer
memset(reply, 0, sizeof(struct pam_response) * num_msg);
for (replies = 0;
replies < num_msg && retStatus == PAM_SUCCESS;
replies++)
{
switch (msg[replies]->msg_style)
{
case PAM_PROMPT_ECHO_ON:
// The caller wants the username
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = malloc(strlen(pAppUserData->pUserName) + 1);
if (reply[replies].resp)
strcpy(reply[replies].resp, pAppUserData->pUserName);
else
{
DbgTrace(0, "Converse- Buffer allocation failure\n", 0);
retStatus = PAM_CONV_ERR;
}
break;
case PAM_PROMPT_ECHO_OFF:
// The caller wants the authentication token
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = malloc(strlen(pAppUserData->pAuthToken) + 1);
if (reply[replies].resp)
{
strcpy(reply[replies].resp, pAppUserData->pAuthToken);
}
else
{
DbgTrace(0, "Converse- Buffer allocation failure\n", 0);
retStatus = PAM_CONV_ERR;
}
break;
case PAM_TEXT_INFO:
case PAM_ERROR_MSG:
// Just return success
reply[replies].resp_retcode = PAM_SUCCESS;
reply[replies].resp = NULL;
break;
default:
// Un-expected
retStatus = PAM_CONV_ERR;
}
}
// Proceed based on the status
if (retStatus == PAM_SUCCESS)
{
*resp = reply;
}
else
{
// Free buffers allocated for the reply
for (replies = 0;
replies < num_msg && retStatus == PAM_SUCCESS;
replies++)
{
if (reply[replies].resp != NULL)
free(reply[replies].resp);
}
free(reply);
}
return retStatus;
}
//++=======================================================================
int
ReadLineIntoBuffer(int connSock, char *pBuffer)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
int i = 0;
char c;
int bytesReceived = 0;
DbgTrace(2, "ReadLineIntoBuffer- Start\n", 0);
// Receive the line
while ((bytesReceived = recv(connSock, &c, 1, 0)) == 1)
{
if (c == '\n')
break;
else
{
pBuffer[i] = c;
i ++;
}
}
// Check for a socket error
if (bytesReceived == 0)
{
DbgTrace(0, "ReadLineIntoBuffer- Socket error\n", 0);
}
DbgTrace(2, "ReadLineIntoBuffer- End, lineLength = %d\n", i);
return i;
}
//++=======================================================================
void
ProcessConnection(int connSock)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
char userName[] = "CasaPrincipal";
char token[8192] = {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", htons(boundAddr.sin_port));
// Now start linstening for connections
if (listen(listenSock, SOMAXCONN) != SOCKET_ERROR)
{
// Loop accepting connections
while (1)
{
addrLen = sizeof(remoteAddr);
connSock = accept(listenSock,
(struct sockaddr*) &remoteAddr,
&addrLen);
if (connSock != INVALID_SOCKET)
{
ProcessConnection(connSock);
// Close the connection socket
closesocket(connSock);
}
else
{
DbgTrace(0, "ExecuteTests- - Accept failed, error = %08X\n", errno);
break;
}
}
}
else
{
DbgTrace(0, "ExecuteTests- Unable to start listening, error = %d", errno);
}
}
else
{
DbgTrace(0, "ExecuteTests- Unable to obtain local address information, error = %d", errno);
}
}
else
{
DbgTrace(0, "ExecuteTests- Unable to bind socket, error = %d", errno);
}
// Close the listen socket
closesocket(listenSock);
}
else
{
DbgTrace(0, "ExecuteTests- Unable to open socket, error = %d\n", errno);
}
DbgTrace(1, "ExecuteTests- End\n", 0);
}
//++=======================================================================
int
main(
int argc,
char* argv[])
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int optionsSpecified = 0;
bool doneScanning = false;
bool invalidOption = false;
int option;
printf("**** server auth_token test ****\n");
// Scan through the options specified
while (!doneScanning)
{
opterr = 0;
option = getopt(argc, argv, "s:D:");
// Proceed based on the result
switch (option)
{
case 'D':
// Set the debug level
printf("DebugLevel = %s\n", optarg);
DebugLevel = atoi(optarg);
optionsSpecified++;
break;
case 's':
// Set the service name
printf("Service name = %s\n", optarg);
pServiceName = optarg;
optionsSpecified++;
break;
case '?':
// Invalid option detected
doneScanning = true;
invalidOption = true;
break;
default:
// Done scanning
doneScanning = true;
break;
}
}
// Do some sanity checking
if (!invalidOption
&& pServiceName != NULL)
{
ExecuteTests();
}
else
{
// Invalid option detected
printf(usage, argv[0]);
}
return 0;
} /*-- main() --*/

View File

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

View File

@ -0,0 +1,241 @@
/***********************************************************************
*
* 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>
*
***********************************************************************/
/***********************************************************************
*
* README for auth_token
*
***********************************************************************/
INTRODUCTION
CASA-auth-token is an authentication token infrastructure with support for multiple
authentication mechanisms with an emphasis on providing a scalable single
sign-on solution.
A key feature of auth_token is that its authentication tokens contain identity
information about the entity being authenticated. This information is made available
to the consuming services. The amount of information contained in the tokens is
configured on a per-service basis. Because of this feature, we say that CASA-auth-token
projects an "Authenticated Identity".
ARCHITECTURE COMPONENTS
The infrastructure provided by auth_token consists of client and server components.
The client components of auth_token consists of a Client Engine, Get Authentication
Token API, Authentication Token Cache, and Authentication Mechanism plug-ins.
The server components of auth_token consists of an Authentication Token Service, a
Verify Authentication Token API, a JAAS module, a PAM module, and an Apache Authentication
Provider module. The Authentication Token Service makes use of Authentication Mechanism
plug-ins, an Identity Data Store Abstraction Layer, and of Identity Token Providers.
SECURITY FEATURES AND DATA FLOW
Communications between the Client Engine and the Authentication Token Service (ATS)
occur over HTTPS. When a client desires to obtain an Authentication Token to access
a particular service it contacts an ATS which then proceeds to inform the client about
the Authentication Policy configured for the service. The policy contains information
about authentication mechanisms supported as well as information about the types of
credentials that the client can utilize to authenticate to the ATS. Once the client
receives the Authentication Policy, it then decides what authentication mechanism to
utilize to authenticate to the ATS based on the available authentication mechanisms
plug-ins as well as the available credentials. During the authentication process, the
ATS associates an identity with the entity being authenticated. The result of this
resolution is saved in a Session Token which is then sent to the client where it is
cached. Once the client is authenticated to the ATS, it then requests Authentication
Tokens from it using the obtained Session Token. When an ATS receives a request for
an Authentication Token, it then verifies the validity of the received Session Token
and then it creates the appropriate Identity Token for the target service which it then
embeds within the Authentication Token. The identity information contained in the
Identity Token as well as the type of Identity Token utilized depends on what is
configured for the tatget service.
Session Tokens and Authentication Tokens are signed by the issuing ATS using Signing
Certificates. Session Tokens and Authentication Tokens have a Lifetime Value associated
with them. Token verification involves verifying the token signatures, verifying that
the tokens where signed by a trusted entity, and verifying that the token lifetime has
not been exceeeded.
The auth_token client/service protocol allows for the authentication of the client entity.
auth_token relies in the server authentication mechanisms of SSL to verify the identity
of the ATS.
IMPLEMENTATION STRATEGY AND CURRENT STATUS
auth_token is currently under development and is not ready to be used in production.
The implementation strategy has been to first complete the framework with all of its
modules, APIs, and packaging to allow application writters to start developing to it.
Once this is done, then the implementation focus will switch to completing the plumbing.
As of this time, a lot of the framework has been completed and there are sample
applications that can be utilized to exercise it. For a more complete picture of where
we are, look at the various TODO lists present in the child folders.
The schedule for completing auth_token is agressive.
REQUIREMENTS FOR BUILDING THE SOFTWARE PACKAGE ON WINDOWS
- Install Visual Studio .NET 2003
- Install Windows Platform SDK for Windows Server 2003 SP1
- Register the platform sdk with VS - Start/All Programs/Windows Platform SDK for Windows Server 2003 SP1/Visual Studio Registration/Register PSDK Directories with Visual Studio
- Install Cygwin - See instructions below.
- Extract Expat-2.0.0.zip in casa source directory parent
- Install Casa
Download and start cygwin install:
Browse to http://sources.redhat.com/cygwin/
Click on "Install or update now!" or "Install Cygwin now"
Cygwin Setup:
Next
Cygwin Setup - Choose Installation Type:
Install from Internet
Next
Cygwin Setup - Choose Installation Directory:
Root Directory: C:\cygwin
Install For: "All Users"
Default Text File Type: DOS
Cygwin Setup - Select Local Package Directory:
Local Package Directory: C:\cygwin-packages
Cygwin Setup - Select Connection Type:
Direct Connection
Choose A Download Site:
ftp://ftp.nas.nasa.gov
Cywin Setup - Select Packages:
Base:
defaults
Devel:
autoconf
automake
libtool
make
pkgconfig
cvs
gcc
gcc-g++
Editors:
vim (optional)
Net:
openssh
openssl
Text:
more
Utils:
clear (optional)
Cygwin Setup - Create Icons:
Finish
Edit cygwin.bat (c:\cygwin\cygwin.bat) to add a call to
%VS71COMNTOOLS%\vsvars32.bat (see example below). This sets up the
Visual Studio tools in Cygwin.
Sample cygwin.bat:
@echo off
call "%VS71COMNTOOLS%\vsvars32.bat" > NUL
C:
chdir C:\cygwin\bin
bash --login -i
REQUIREMENTS FOR BUILDING THE SOFTWARE PACKAGE ON LINUX
Install latest mono and mono-devel RPM - Obtain RPMs from
www.go-mono.org.
BUILDING THE SOFTWARE PACKAGE
Windows: Start at Step 1.
Linux: Skip to Step 2.
1. Run cygwin.bat to start up Cygwin.
2. Generate autotools files:
./autogen.sh --prefix=/<install_dir> [--enable-debug]
(<install_dir> is some writable directory where 'make install' will
install files for testing.
3. To reconfigure later, or to configure software that came from a source
distribution (.tar.gz) file, use configure.
./configure --prefix/<install_dir> [--enable-debug]
(run ./configure --help for more options)
4. Select your make target, here are a few interesting ones:
make [all] - build product files (package files not included)
make clean - clean up files built by 'make all'
make package - build product and package files
make package-clean - clean up package files
make install - install product files to <install_dir> specified by
--prefix during configure
make uninstall - undo 'make install'
make dist - build a source distribution tarball.
make distclean - removes files to return state back to same as the
source distribution (configure, Makefile.in files, and other distributed
autotools files are not removed)
make maintainer-clean - removes files to return state back to same as
the CVS checkout (you will need to run ./autogen.sh again before running
make again)
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.

View File

@ -0,0 +1,17 @@
/***********************************************************************
*
* TODO for auth_token
*
***********************************************************************/
INTRODUCTION
This file contains a list of the items still outstanding for auth_token.
Note: There are TODO lists under each auth_token component. This file just
details outstanding items at the project level.
OUTSTANDING ITEMS
- Add mechanism to try communicating with ATS over port 443 if communications
over port 2645 fail.

130
CASA-auth-token/server/autogen.sh Executable file
View File

@ -0,0 +1,130 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
cd $srcdir
PROJECT=CASA_auth_token_native
TEST_TYPE=-f
FILE=configure.in
DIE=0
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have autoconf installed to compile $PROJECT."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
AUTOMAKE=automake-1.9
ACLOCAL=aclocal-1.9
($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
AUTOMAKE=automake
ACLOCAL=aclocal
}
($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have automake installed to compile $PROJECT."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
if test "$DIE" -eq 1; then
exit 1
fi
test $TEST_TYPE $FILE || {
echo "You must run this script in the top-level $PROJECT directory"
exit 1
}
if test -z "$*"; then
echo "I am going to run ./configure with no arguments - if you wish "
echo "to pass any to it, please specify them on the $0 command line."
fi
case $CC in
*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;;
esac
for coin in `find $srcdir -name configure.in -print`
do
dr=`dirname $coin`
if test -f $dr/NO-AUTO-GEN; then
echo skipping $dr -- flagged as no auto-gen
else
echo processing $dr
macrodirs=`sed -n -e 's,AM_ACLOCAL_INCLUDE(\(.*\)),\1,gp' < $coin`
( cd $dr
aclocalinclude="$ACLOCAL_FLAGS"
for k in $macrodirs; do
if test -d $k; then
aclocalinclude="$aclocalinclude -I $k"
##else
## echo "**Warning**: No such directory \`$k'. Ignored."
fi
done
if grep "^AM_GNU_GETTEXT" configure.in >/dev/null; then
if grep "sed.*POTFILES" configure.in >/dev/null; then
: do nothing -- we still have an old unmodified configure.in
else
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running gettextize... Ignore non-fatal messages."
echo "no" | gettextize --force --copy
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
fi
if grep "^AM_GNOME_GETTEXT" configure.in >/dev/null; then
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running gettextize... Ignore non-fatal messages."
echo "no" | gettextize --force --copy
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
if grep "^AM_GLIB_GNU_GETTEXT" configure.in >/dev/null; then
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running gettextize... Ignore non-fatal messages."
echo "no" | glib-gettextize --force --copy
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
fi
if grep "^AM_PROG_LIBTOOL" configure.in >/dev/null; then
echo "Running libtoolize..."
libtoolize --force --copy
fi
echo "Running $ACLOCAL $aclocalinclude ..."
$ACLOCAL $aclocalinclude
if grep "^AM_CONFIG_HEADER" configure.in >/dev/null; then
echo "Running autoheader..."
autoheader
fi
echo "Running $AUTOMAKE --gnu $am_opt ..."
$AUTOMAKE --add-missing --gnu $am_opt
echo "Running autoconf ..."
autoconf
)
fi
done
conf_flags="--config-cache --enable-maintainer-mode --enable-compile-warnings" #--enable-iso-c
cd "$ORIGDIR"
if test x$NOCONFIGURE = x; then
echo Running $srcdir/configure $conf_flags "$@" ...
$srcdir/configure $conf_flags "$@" \
&& echo Now type \`make\' to compile $PROJECT || exit 1
else
echo Skipping configure process.
fi

View File

@ -0,0 +1,290 @@
#######################################################################
#
# 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.
#
#
#######################################################################
AC_INIT(CASA_auth_token_server, 1.7.795,,CASA_auth_token_server)
AC_CONFIG_SRCDIR(autogen.sh)
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE(tar-pax)
RELEASE=`date +%Y%m%d_%H%M`
AC_SUBST(RELEASE)
AM_MAINTAINER_MODE
#
# Check for a valid C# compiler
#
#AC_CHECK_PROG(CSC, csc, csc)
#test -z "$CSC" && AC_CHECK_PROG(CSC, mcs, mcs)
#test -z "$CSC" && AC_MSG_ERROR([no acceptable C Sharp compiler found in \$PATH])
#
# Check for valid C# compiler in linux
#
case $host_os in
cygwin*)
;;
*)
AC_CHECK_PROG(CSC, csc, csc)
test -z "$CSC" && AC_CHECK_PROG(CSC, mcs, mcs)
test -z "$CSC" && AC_MSG_ERROR([no acceptable C Sharp compiler found in \$PATH])
;;
esac
case $CSC in
#
# Mono-specific configuration
#
mcs)
CSC_EXEFLAG=/target:exe
CSC_LIBFLAG=/target:library
CSC_EXEFLAG=/target:exe
CSC_WINEXEFLAG=/target:winexe
CSCFLAGS='/d:MONO /warn:4 /d:TRACE -d:LINUX'
CSCFLAGS_DEBUG="/debug+ /d:DEBUG"
CSCFLAGS_OPTIMIZE="/optimize+"
MONO=mono
MONO_DEBUG='mono --debug'
MONO_PATH=
SYSTEM_XML='System.Xml.dll'
;;
#
# .NET-specific configuration
#
csc)
CSC_EXEFLAG=/target:exe
CSC_LIBFLAG=/target:library
CSC_EXEFLAG=/target:exe
CSC_WINEXEFLAG=/target:winexe
CSCFLAGS='/d:DOTNET /warn:4 /d:TRACE /nologo'
CSCFLAGS_DEBUG="/debug+ /d:DEBUG"
CSCFLAGS_OPTIMIZE="/optimize+"
MONO=
MONO_DEBUG=
MONO_PATH=
SYSTEM_XML='System.XML.dll'
;;
esac
AC_SUBST(CSC)
AC_SUBST(CSC_EXEFLAG)
AC_SUBST(CSC_LIBFLAG)
AC_SUBST(CSC_WINEXEFLAG)
AC_SUBST(CSCFLAGS)
AC_SUBST(CSCFLAGS_DEBUG)
AC_SUBST(MONO)
AC_SUBST(MONO_PATH)
AC_SUBST(SYSTEM_XML)
SRCDIR='$(top_srcdir)'
DOCDIR="$SRCDIR/doc"
TOOLDIR='$(top_srcdir)/tools'
AC_SUBST(SRCDIR)
AC_SUBST(DOCDIR)
AC_SUBST(TOOLDIR)
EMPTY=
SPACE='$(EMPTY) $(EMPTY)'
AC_SUBST(EMPTY)
AC_SUBST(SPACE)
#
# Check for operating system and set TARGET_OS
#
case $host_os in
cygwin*)
TARGET_OS='windows'
;;
*)
TARGET_OS='linux'
;;
esac
AC_SUBST(TARGET_OS)
AM_CONDITIONAL(LINUX, test "$TARGET_OS" = "linux")
AM_CONDITIONAL(WINDOWS, test "$TARGET_OS" = "windows")
#
# Check for architecture and set TARGET_ARCH
# ia64 needs to be treated as non64.
case $target_cpu in
x86_64|p*pc64|s390x)
LIB=lib64
BIN=bin64
;;
*ia64|*)
LIB=lib
BIN=bin
;;
esac
AC_SUBST(LIB)
AC_SUBST(BIN)
AM_CONDITIONAL(LIB64, test "$LIB" = lib64)
#
#
# Set platform-specific variables
#
case $TARGET_OS in
#
# Linux-specific configuration
#
linux)
#
# Set variables
#
COMMON_CLEAN_FILES=''
ICON_EXT='.ico'
ICON_FLAG='/resource:'
PLATFORM_SUBDIRS=$LINUX_SUBDIRS
SEP='/'
LINK=gcc
;;
#
# Windows-specific configuration
#
windows)
COMMON_CLEAN_FILES='*.suo */*.suo *.csproj.user */*.csproj.user bin obj */bin */obj *.xml */*.xml *.pdb */*.pdb'
ICON_EXT='.ico'
ICON_FLAG='/win32icon:'
PLATFORM_SUBDIRS=$WINDOWS_SUBDIRS
SEP='$(EMPTY)\\$(EMPTY)'
LINK=link.exe
;;
esac
AC_SUBST(COMMON_CLEAN_FILES)
AC_SUBST(ICON_EXT)
AC_SUBST(ICON_FLAG)
AC_SUBST(PLATFORM_SUBDIRS)
AC_SUBST(SEP)
AC_SUBST(LINK)
#
# Run standard macros
#
AM_PROG_CC_STDC
AC_PROG_INSTALL
AC_HEADER_STDC
#######
#
# set CFLAGS
#
case $host_os in
linux*)
CFLAGS="$CFLAGS"
;;
cygwin*)
CC=cl.exe
CFLAGS="-D WIN32 -D SSCS_WIN32_PLAT_F -D N_PLAT_CLIENT -MT -Ox"
;;
esac
#
# Handle --enable-debug
#
AC_ARG_ENABLE(debug, [
--enable-debug configure the Makefiles to build in DEBUG mode],
[case "${enableval}" in
yes) enable_debug=true ;;
no) enable_debug=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
esac],[enable_debug=false])
AM_CONDITIONAL(DEBUG, test x$enable_debug = xtrue)
if test "$enable_debug" = "true"
then
# Build debug version.
# CFLAGS="$CFLAGS_DEBUG $CFLAGS -DDBG -DDEBUG"
CFLAGS="$CFLAGS_DEBUG $CFLAGS -g -DDBG -DDEBUG \
-fPIC -DPIC -DSSCS_LINUX_PLAT_F -O2 -fmessage-length=0 -Wall \
-D_REENTRANT -DALIGNMENT -DN_PLAT_UNIX \
-DUNIX -DLINUX -DIAPX38"
CSCFLAGS="$CSCFLAGS_DEBUG $CSCFLAGS"
CXXFLAGS="$CXXFLAGS_DEBUG $CXXFLAGS"
DEVENV_CONFIGURATION=Debug
MONO=$MONO_DEBUG
else
# Build optimized version.
CFLAGS="$CFLAGS_OPTIMIZE $CFLAGS -g -fPIC -DPIC \
-DSSCS_LINUX_PLAT_F -O2 -fmessage-length=0 -Wall \
-D_REENTRANT -DALIGNMENT -DN_PLAT_UNIX \
-DUNIX -DLINUX -DIAPX38"
CSCFLAGS="$CSCFLAGS_OPTIMIZE $CSCFLAGS"
CXXFLAGS="$CXXFLAGS_OPTIMIZE $CXXFLAGS"
DEVENV_CONFIGURATION=Release
fi
AC_SUBST(CSCFLAGS)
AC_SUBST(DEVENV_CONFIGURATION)
##comment out due to build failure
# Check for GCC version to add fstack-protector flag
#
#GCC_VER="`gcc -dumpversion`"
#case "$GCC_VER" in
# 3*)
# ;;
# 4*)
# CFLAGS="$CFLAGS -fstack-protector"
# ;;
# *)
# ;;
#esac
AC_SUBST(GCC_VER)
#
# Configure PKG_CONFIG
#
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
if test "x$PKG_CONFIG" = "xno"; then
AC_MSG_ERROR([You need to install pkg-config])
fi
#
# Configure files
#
AC_OUTPUT([
Makefile
package/Makefile
package/linux/Makefile
package/linux/CASA_auth_token_server.spec
include/Makefile
utilities/Makefile
utilities/IpcLibs/Makefile
utilities/IpcLibs/linux/Makefile
utilities/IpcLibs/linux/common/Makefile
utilities/IpcLibs/linux/client/Makefile
utilities/IpcLibs/linux/server/Makefile
AuthTokenValidate/Makefile
AuthTokenValidate/linux/Makefile
AuthTokenValidate/idenTokenProviders/Makefile
AuthTokenValidate/idenTokenProviders/casa/Makefile
AuthTokenValidate/idenTokenProviders/casa/linux/Makefile
AuthTokenValidate/Svc/Makefile
AuthTokenValidate/Svc/linux/Makefile
PamSupport/Makefile
PamSupport/linux/Makefile
ApacheSupport/Makefile
ApacheSupport/2.2/Makefile
ApacheSupport/2.2/linux/Makefile
])

View File

@ -0,0 +1,40 @@
#######################################################################
#
# 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 =
DIST_SUBDIRS =
CFILES =
EXTRA_DIST = *.h
.PHONY: package package-clean package-install package-uninstall
package package-clean package-install package-uninstall:
$(MAKE) -C $(TARGET_OS) $@
clean-local:
if [ -d lib ]; then rm -rf lib; fi
maintainer-clean-local:
rm -f Makefile.in

View File

@ -0,0 +1,278 @@
/***********************************************************************
*
* 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 _IPCCLIENT_
#define _IPCCLIENT_
//===[ Header files specific to this module ]==============================
//===[ Manifest constants ]==============================
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef INOUT
#define INOUT
#endif
//===[ Structure Definitions ]==============================
//===[ Function Prototypes ]==============================
//++=======================================================================
extern
int
IpcClientOpenUnixRemoteEndPoint(
IN char *pSocketFileName,
IN int maxRpcRetries,
INOUT uint32_t *pEndPointHandle);
//
// Arguments In: port - Server's listening port number.
//
// address - The server's IP Address. Use
// 0x7F000001 if the server is local.
//
// maxRpcRetries - Maximum number of Rpc retries that
// should be utilized when submitting
// a request to the endpoint. A value
// of zero requests that the default
// setting be utilized.
//
// Arguments Out: pEndPointHandle - Pointer to variable that will receive
// the endpoint handle.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to open a UNIX (PF_UNIX) remote endpoint.
//
// Note: The service should have been initialized before calling
// this procedure.
//
//=======================================================================--
typedef
int
(*PFN_IpcClientOpenUnixRemoteEndPoint)(
IN char *pSocketFileName,
IN int maxRpcRetries,
INOUT uint32_t *pEndPointHandle);
//++=======================================================================
extern
int
IpcClientOpenInetRemoteEndPoint(
IN unsigned short int port,
IN uint32_t address,
IN int maxRpcRetries,
INOUT uint32_t *pEndPointHandle);
//
// Arguments In: port - Server's listening port number.
//
// address - The server's IP Address. Use
// 0x7F000001 if the server is local.
//
// maxRpcRetries - Maximum number of Rpc retries that
// should be utilized when submitting
// a request to the endpoint. A value
// of zero requests that the default
// setting be utilized.
//
// Arguments Out: pEndPointHandle - Pointer to variable that will receive
// the endpoint handle.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to open a TCP (AF_INET) remote endpoint.
//
// Note: The service should have been initialized before calling
// this procedure.
//
//=======================================================================--
typedef
int
(*PFN_IpcClientOpenInetRemoteEndPoint)(
IN unsigned short int port,
IN uint32_t address,
IN int maxRpcRetries,
INOUT uint32_t *pEndPointHandle);
//++=======================================================================
extern
int
IpcClientCloseRemoteEndPoint(
IN uint32_t endPointHandle);
//
// Arguments In: endpointHandle - Handle of the endpoint being closed.
//
//
// Arguments Out: None.
// the endpoint handle.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to close a remote endpoint.
//
// Note: The service should have been initialized before calling
// this procedure.
//
//=======================================================================--
typedef
int
(*PFN_IpcClientCloseRemoteEndPoint)(
IN uint32_t endPointHandle);
//++=======================================================================
extern
int
IpcClientSubmitReq(
IN uint32_t endPointHandle,
IN char *pClientData,
IN int clientDataLen,
INOUT char **ppServerData,
INOUT int *pServerDataLen);
//
// Arguments In: endPointHandle - Handle of the remote endpoint that will
// be the target of the request.
//
// pClientData - Pointer to client data that must be sent to
// the server. Buffer is NEVER released by the
// procedure.
//
// clientDataLen - Length of the client data.
//
// Arguments Out: ppServerData - Pointer to variable that will receive a
// pointer to the buffer containing the data
// received from the server.
//
// The returned buffer always contains a NULL after the
// data indicated. You may be able to leverage this to
// treat the data as a NULL terminated string in cases
// where the request consists of ASCII characters.
//
// pServerDataLen - Pointer to variable that will receive the
// length of the data received from the server.
//
// Returns: 0 == Request completed gracefully
// -1 == Request did not complete gracefully
//
// Abstract: Method to submit a request.
//
// Notes: The routine blocks until the request completes.
//
// The buffer returned with the server data must be released
// by the calling application by calling free().
//
//=======================================================================--
typedef
int
(*PFN_IpcClientSubmitReq)(
IN uint32_t endPointHandle,
IN char *pClientData,
IN int clientDataLen,
INOUT char **ppServerData,
INOUT int *pServerDataLen);
//++=======================================================================
extern
int
IpcClientInit(
IN char *pName,
IN bool multithreaded,
IN int debugLevel,
IN bool useSyslog);
//
// Arguments In: pName - Pointer to string containing the name that the
// calling application wants associated with the
// debug logs emitted by the library.
//
// multithreaded - Set to TRUE if the process is
// multithreaded.
//
// debugLevel - The level that the library should use for
// determining what information should be logged
// for debugging purposes. 0 being the lowest
// level.
//
// useSyslog - Set to TRUE to log debug statements using Syslog,
// else debugs are log to stderr.
//
// Arguments Out: None.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to initialize the IPC infrastructure for process.
//
// Note: It is necessary to call the appropriate function to
// set the server address before a request can be submitted.
//
//=======================================================================--
typedef
int
(*PFN_IpcClientInit)(
IN char *pName,
IN bool multithreaded,
IN int debugLevel,
IN bool useSyslog);
//++=======================================================================
extern
void
IpcClientShutdown(void);
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Method to shutdown the IPC infrastructure for process.
//
//=======================================================================--
typedef
void
(*PFN_IpcClientShutdown)(void);
#endif // _IPCCLIENT_
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,305 @@
/***********************************************************************
*
* 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 _CASA_S_AUTHTOKEN_H_
#define _CASA_S_AUTHTOKEN_H_
#if defined(__cplusplus) || defined(c_plusplus)
extern "C"
{
#endif
//===[ Include files ]=====================================================
#include <micasa_types.h>
#include <casa_status.h>
//===[ Type definitions ]==================================================
#ifndef SSCS_CALL
#if defined(WIN32)
#define SSCS_CALL __stdcall
#else
#define SSCS_CALL
#endif
#endif
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
/**************************************************************************
***************************************************************************
** **
** Principal Interface Definition **
** **
***************************************************************************
**************************************************************************/
//++=======================================================================
typedef
int
(SSCS_CALL *PFNPrincipalIf_AddReference)(
IN const void *pIfInstance);
//
// Arguments:
// pIfInstance -
// Pointer to interface object.
//
// Returns:
// Interface reference count.
//
// Description:
// Increases interface reference count.
//=======================================================================--
//++=======================================================================
typedef
void
(SSCS_CALL *PFNPrincipalIf_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 *PFNPrincipalIf_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 *PFNPrincipalIf_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 *PFNPrincipalIf_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 *PFNPrincipalIf_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.
//=======================================================================--
//
// Principal Interface Object
//
typedef struct _PrincipalIf
{
PFNPrincipalIf_AddReference addReference;
PFNPrincipalIf_ReleaseReference releaseReference;
PFNPrincipalIf_GetIdentityId getIdentityId;
PFNPrincipalIf_GetSourceName getSourceName;
PFNPrincipalIf_GetSourceUrl getSourceUrl;
PFNPrincipalIf_AttributeEnumerate attributeEnumerate;
} PrincipalIf, *PPrincipalIf;
/**************************************************************************
***************************************************************************
** **
** Validate Authentication Token API **
** **
***************************************************************************
**************************************************************************/
//++=======================================================================
extern 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.
//
//=======================================================================--
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif // #if defined(__cplusplus) || defined(c_plusplus)
#endif // #ifndef _CASA_S_AUTHTOKEN_H_

View File

@ -0,0 +1,259 @@
/***********************************************************************
*
* 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 _IPCSERVER_
#define _IPCSERVER_
//===[ Header files specific to this module ]==============================
//===[ Manifest constants ]==============================
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef INOUT
#define INOUT
#endif
//===[ Structure Definitions ]==============================
//===[ Function Prototypes ]==============================
//++=======================================================================
extern
int32_t
IpcServerGetRequest(void);
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: The id of the pending request.
// 0 == Not able to wait for request.
//
// Abstract: A server thread invokes this method to be informed when
// a request is received that needs to be acted upon.
//
// Notes: The routine blocks until a request becomes available or
// until the IpcServer is shutdown.
//
// An application can execute this method from multiple
// threads to allow requests to be process concurrently.
//
//=======================================================================--
//++=======================================================================
extern
int32_t
IpcServerGetRequestData(
IN int32_t requestId,
INOUT char **ppReqData);
//
// Arguments In: requestId - The id of the request being processed.
//
// Arguments Out: ppReqData - Pointer to variable that will receive a
// pointer to the buffer containing the request
// data the client.
//
// Returns: The length of the request data returned.
//
// Abstract: Method to obtain the data associated with a particular
// request.
//
// Notes: The returned buffer SHOULD NOT be released by the calling
// application.
//
// The returned buffer always contains a NULL after the
// data indicated. You may be able to leverage this to
// treat the data as a NULL terminated string in cases
// where the request consists of ASCII characters.
//
//=======================================================================--
//++=======================================================================
extern
void
IpcServerCompleteRequest(
IN int32_t requestId,
IN char *pReplyData);
//
// Arguments In: requestId - The id of the request being completed.
//
// pReplyData - Pointer to reply data that must be sent to
// the client for this request.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Method to complete a request being processed.
//
// Notes: The returned buffer will not NOT be released by the method.
//
//=======================================================================--
//++=======================================================================
extern
void
IpcServerAbortRequest(
IN int32_t requestId);
//
// Arguments In: requestId - The id of the request being aborted.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Method to abort a request being processed.
//
// Notes:
//
//=======================================================================--
//++=======================================================================
extern
int
IpcServerStart(void);
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to enable the reception of server requests.
//
// Note: The service needs to be initialized and the listen address
// needs to be set before calling this procedure.
//
//=======================================================================--
//++=======================================================================
extern
int
IpcServerSetUnAddress(
IN char *pSocketFileName);
//
// Arguments In: pSocketFileName - Pointer to string containing the name
// of the socket file to listen on.
//
// Arguments Out: None.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to set the socket file name to utilize for
// communicating with the server via DOMAIN sockets.
//
// Note: The service needs to be initialized before calling this procedure.
//
//=======================================================================--
//++=======================================================================
extern
int
IpcServerSetInAddress(
IN unsigned short int listenPort);
//
// Arguments In: serverPort - Server's listening port number.
//
// Arguments Out: None.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to set the address to utilize for communicating
// with the server via TCP sockets.
//
// Note: The service needs to be initialized before calling this procedure.
//
//=======================================================================--
//++=======================================================================
extern
int
IpcServerInit(
IN char *pName,
IN int debugLevel,
IN bool useSyslog);
//
// Arguments In: pName - Pointer to string containing the name that the
// calling application wants associated with the
// debug logs emitted by the library.
//
// debugLevel - The level that the library should use for
// determining what information should be logged
// for debugging purposes. 0 being the lowest
// level.
//
// useSyslog - Set to TRUE to log debug statements using Syslog,
// else debugs are log to stderr.
//
// Arguments Out: None.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to initialize the IPC infrastructure for process.
//
// Note: It is necessary to call the start procedure to start
// servicing requests.
//
//=======================================================================--
//++=======================================================================
extern
void
IpcServerShutdown(void);
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Method to shutdown the IPC service.
//
// Note:
//
//=======================================================================--
#endif // _IPCSERVER_
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,187 @@
/***********************************************************************
*
* Copyright (C) 2005-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.
*
***********************************************************************/
#ifndef _LIST_ENTRY_H_
#define _LIST_ENTRY_H_
#if defined(__cplusplus) || defined(c_plusplus)
extern "C"
{
#endif
//===[ Include files ]=====================================================
//#include <micasa_types.h>
//===[ Type definitions ]==================================================
#ifndef CSAPI
#if defined(WIN32)
#define CSAPI __stdcall
#else
#define CSAPI
#endif
#endif
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef INOUT
#define INOUT
#endif
#ifndef WIN32
//
// LIST_ENTRY Type
// Doubly linked list structure
//
typedef struct _LIST_ENTRY
{
struct _LIST_ENTRY * volatile Flink;
struct _LIST_ENTRY * volatile Blink;
} LIST_ENTRY, *PLIST_ENTRY;
#endif
//===[ Inlines functions ]===============================================
//
// Inline functions for operating on LIST_ENTRY double-linked lists
//
__inline static void InitializeListHead(
IN PLIST_ENTRY pListEntry )
{
pListEntry->Flink = pListEntry->Blink = pListEntry;
}
__inline static void InsertEntryAfter(
IN PLIST_ENTRY pListEntry,
IN PLIST_ENTRY pAfterEntry )
{
pListEntry->Flink = pAfterEntry->Flink;
pListEntry->Blink = pAfterEntry;
pListEntry->Flink->Blink = pAfterEntry->Flink = pListEntry;
}
__inline static void InsertEntryBefore(
IN PLIST_ENTRY pListEntry,
IN PLIST_ENTRY pBeforeEntry )
{
pListEntry->Flink = pBeforeEntry;
pListEntry->Blink = pBeforeEntry->Blink;
pListEntry->Blink->Flink = pBeforeEntry->Blink = pListEntry;
}
__inline static void InsertHeadList(
IN PLIST_ENTRY pListHead,
IN PLIST_ENTRY pListEntry )
{
pListEntry->Blink = pListHead;
pListEntry->Flink = pListHead->Flink;
pListEntry->Flink->Blink = pListHead->Flink = pListEntry;
}
__inline static void InsertTailList(
IN PLIST_ENTRY pListHead,
IN PLIST_ENTRY pListEntry )
{
pListEntry->Flink = pListHead;
pListEntry->Blink = pListHead->Blink;
pListEntry->Blink->Flink = pListHead->Blink = pListEntry;
}
__inline static bool IsListEmpty(
IN PLIST_ENTRY pListHead )
{
bool rc = false;
if(pListHead->Flink == pListHead)
rc = true;
return(rc);
}
__inline static void RemoveEntryList(
IN PLIST_ENTRY pListEntry )
{
pListEntry->Flink->Blink = pListEntry->Blink;
pListEntry->Blink->Flink = pListEntry->Flink;
pListEntry->Flink = pListEntry->Blink = (PLIST_ENTRY) 0xbaadf00d;
}
__inline static PLIST_ENTRY RemoveHeadList(
IN PLIST_ENTRY pListHead )
{
PLIST_ENTRY Entry = (PLIST_ENTRY)0;
if(pListHead->Flink != pListHead)
{
Entry = pListHead->Flink;
RemoveEntryList(Entry);
}
return(Entry);
}
__inline static PLIST_ENTRY RemoveTailList(
IN PLIST_ENTRY pListHead )
{
PLIST_ENTRY Entry= (PLIST_ENTRY)0;
if(pListHead->Blink != pListHead)
{
Entry = pListHead->Blink;
RemoveEntryList(Entry);
}
return(Entry);
}
__inline static PLIST_ENTRY GetFirstListEntry(
IN PLIST_ENTRY pList)
{
PLIST_ENTRY Entry = (PLIST_ENTRY)0;
if(pList != pList->Flink)
Entry = pList->Flink;
return(Entry);
}
__inline static PLIST_ENTRY GetNextListEntry(
IN PLIST_ENTRY pList,
IN PLIST_ENTRY pEntry)
{
PLIST_ENTRY Entry = (PLIST_ENTRY)0;
if(pList != pEntry->Flink)
Entry = pEntry->Flink;
return(Entry);
}
//=========================================================================
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif // #if defined(__cplusplus) || defined(c_plusplus)
#endif // #ifndef _LIST_ENTRY_H_

View File

@ -0,0 +1,38 @@
#######################################################################
#
# 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
EXTRA_DIST =
.PHONY: package package-clean package-install package-uninstall
package package-clean package-install package-uninstall:
$(MAKE) -C $(TARGET_OS) $@
clean-local:
if [ -d lib ]; then rm -rf lib; fi
maintainer-clean-local:
rm -f Makefile.in

View File

@ -0,0 +1,83 @@
-------------------------------------------------------------------
Thu Nov 9 17:16:36 MST 2006 - jluciani@novell.com
- Finished the changes to enable client/ATS communications
over SSL.
-------------------------------------------------------------------
Tue Nov 7 16:01:11 MST 2006 - jluciani@novell.com
- Made changes to enable client/ats communication over SSL. (Not quite
done with this yet).
- Updated the make system to allow Windows builds to be made from
the command line using Cygwin.
-------------------------------------------------------------------
Thu Oct 19 09:20:24 MDT 2006 - jluciani@novell.com
- Created client-devel RPM.
- Made changes to conform to updates made to the Java components
with regard to the layout of files.
-------------------------------------------------------------------
Tue Oct 10 08:46:22 MDT 2006 - jluciani@novell.com
- Brought up to date the README and TODO files.
-------------------------------------------------------------------
Mon Oct 9 09:28:37 MDT 2006 - jluciani@novell.com
- Cleaned up compiler warnings that were present in some of the
components.
-------------------------------------------------------------------
Fri Oct 6 14:22:54 MDT 2006 - schoi@novell.com
- Add the CASA build check as dependency in spec file
-------------------------------------------------------------------
Thu Oct 5 15:21:39 MDT 2006 - jluciani@novell.com
- Ported the client to Linux and created the CASA_auth_token_client package.
-------------------------------------------------------------------
Mon Oct 2 11:47:16 MDT 2006 - jluciani@novell.com
- Made spec file modifications suggested by SuSE. The changes entailed
leveraging RPM macros instead of using my own scripts to make the
RPM more solid.
-------------------------------------------------------------------
Thu Sep 14 17:41:40 MDT 2006 - jluciani@novell.com
- Added rc script for Validate AuthToken Service.
-------------------------------------------------------------------
Thu Sep 14 09:48:54 MDT 2006 - jluciani@novell.com
- Created the Validate AuthToken Service and made all of the necessary changes
to allow it to be consumed by the AuthTokenValidate library.
- Also made necessary spec file changes to support our configuration.
-------------------------------------------------------------------
Tue Sep 5 08:37:35 MDT 2006 - jluciani@novell.com
- Created client/server IPC libraries that will be utilized by libcasa_s_authtoken
to communicate with the Java Validate AuthToken Service (yet to be created) over
DOMAIN sockets. The service will utilize the libraries via JNI to be able to
process requests sent using DOMAIN sockets.
-------------------------------------------------------------------
Tue Aug 15 10:09:32 MDT 2006 - schoi@novell.com
- Fixed CASA_auth_token_devel build requirement for CASA_auth_token_svc
-------------------------------------------------------------------
Mon Aug 7 10:28:32 MDT 2006 - schoi@novell.com
- This file has been created for CASA_auth_token_native project for the first
time.
-------------------------------------------------------------------

View File

@ -0,0 +1,83 @@
-------------------------------------------------------------------
Thu Nov 9 17:16:36 MST 2006 - jluciani@novell.com
- Finished the changes to enable client/ATS communications
over SSL.
-------------------------------------------------------------------
Tue Nov 7 16:01:11 MST 2006 - jluciani@novell.com
- Made changes to enable client/ats communication over SSL. (Not quite
done with this yet).
- Updated the make system to allow Windows builds to be made from
the command line using Cygwin.
-------------------------------------------------------------------
Thu Oct 19 09:20:24 MDT 2006 - jluciani@novell.com
- Created client-devel RPM.
- Made changes to conform to updates made to the Java components
with regard to the layout of files.
-------------------------------------------------------------------
Tue Oct 10 08:46:22 MDT 2006 - jluciani@novell.com
- Brought up to date the README and TODO files.
-------------------------------------------------------------------
Mon Oct 9 09:28:37 MDT 2006 - jluciani@novell.com
- Cleaned up compiler warnings that were present in some of the
components.
-------------------------------------------------------------------
Fri Oct 6 14:22:54 MDT 2006 - schoi@novell.com
- Add the CASA build check as dependency in spec file
-------------------------------------------------------------------
Thu Oct 5 15:21:39 MDT 2006 - jluciani@novell.com
- Ported the client to Linux and created the CASA_auth_token_client package.
-------------------------------------------------------------------
Mon Oct 2 11:47:16 MDT 2006 - jluciani@novell.com
- Made spec file modifications suggested by SuSE. The changes entailed
leveraging RPM macros instead of using my own scripts to make the
RPM more solid.
-------------------------------------------------------------------
Thu Sep 14 17:41:40 MDT 2006 - jluciani@novell.com
- Added rc script for Validate AuthToken Service.
-------------------------------------------------------------------
Thu Sep 14 09:48:54 MDT 2006 - jluciani@novell.com
- Created the Validate AuthToken Service and made all of the necessary changes
to allow it to be consumed by the AuthTokenValidate library.
- Also made necessary spec file changes to support our configuration.
-------------------------------------------------------------------
Tue Sep 5 08:37:35 MDT 2006 - jluciani@novell.com
- Created client/server IPC libraries that will be utilized by libcasa_s_authtoken
to communicate with the Java Validate AuthToken Service (yet to be created) over
DOMAIN sockets. The service will utilize the libraries via JNI to be able to
process requests sent using DOMAIN sockets.
-------------------------------------------------------------------
Tue Aug 15 10:09:32 MDT 2006 - schoi@novell.com
- Fixed CASA_auth_token_devel build requirement for CASA_auth_token_svc
-------------------------------------------------------------------
Mon Aug 7 10:28:32 MDT 2006 - schoi@novell.com
- This file has been created for CASA_auth_token_native project for the first
time.
-------------------------------------------------------------------

View File

@ -0,0 +1,365 @@
#
# spec file for the CASA_auth_token server ( Version @VERSION@ )
#
# Copyright (c) 2006 SUSE LINUX Products GmbH, Nuernberg, Germany.
# This file and all modifications and additions to the pristine
# package are under the same license as the package itself.
#
# Please submit bugfixes or comments via http://bugs.opensuse.org/
#
# norootforbuild
Name: CASA_auth_token_server
%define cfg Release
%define debug_opt ""
URL: http://www.novell.com/products
BuildRequires: CASA-devel apache2-devel expat gcc-c++ glib2-devel libstdc++ libstdc++-devel mono-devel pam-devel pkgconfig update-alternatives java-1_5_0-ibm java-1_5_0-ibm-devel java-1_5_0-ibm-alsa sysvinit insserv glade-sharp glade-sharp2
%define prefix /usr
License: LGPL
Group: System/Libraries
Autoreqprov: on
%define bldno @VERSION@
Version: @VERSION@
Release: 1
Summary: Novell CASA Authentication Token Libraries for C/C++ Server Applications
Source: %{name}-%{version}.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Requires: expat binutils java-1_5_0-ibm CASA_auth_token_jaas_support sysvinit insserv
PreReq: %fillup_prereq %insserv_prereq
PreReq: /usr/bin/awk, /usr/bin/test, /bin/grep, /bin/cat, /usr/bin/install, /bin/pwd
PreReq: /usr/sbin/groupadd, /usr/sbin/useradd, /usr/sbin/userdel, /usr/bin/getent
%description
CASA_auth_token is an authentication token infrastructure with support
for multiple authentication mechanisms with an emphasis on providing a
scalable single sign-on solution.
A key feature of CASA_auth_token is that its authentication tokens
contain identity information about the entity being authenticated. This
information is made available to the consuming services. The amount of
information contained in the tokens is configured on a per-service
basis. Because of this feature, we say that CASA_auth_token projects an
"Authenticated Identity".
The CASA_auth_token_server package contains the authentication token
verification library for C/C++ applications. It is recommended that
this library not be invoked directly by applications, instead it is
recomended that appplication invoke its services through the support
modules provided to integrate with PAM or the Apache Web Server.
Authors:
--------
Juan Carlos Luciani - jluciani@novell.com
%package -n CASA_auth_token_pam_support
Summary: Novell CASA Authentication Token PAM Support Components
Group: System/Libraries
Requires: CASA_auth_token_server pam
%description -n CASA_auth_token_pam_support
CASA_auth_token is an authentication token infrastructure with support
for multiple authentication mechanisms with an emphasis on providing a
scalable single sign-on solution.
A key feature of CASA_auth_token is that its authentication tokens
contain identity information about the entity being authenticated. This
information contained in the tokens is configured on a per-service
basis. Because of this feature, we say that CASA_auth_token projects an
"Authenticated Identity".
The CASA_auth_token_pam_support package contains the CASA (Common
Authentication Services Adapter) authentication token infrastructure
PAM module for token verification.
Authors:
--------
Juan Carlos Luciani - jluciani@novell.com
%package -n CASA_auth_token_apache2_2_support
Summary: Novell CASA Authentication Token Apache2_2 Support Components
Group: System/Libraries
Requires: apache2 CASA_auth_token_server
%description -n CASA_auth_token_apache2_2_support
CASA_auth_token is an authentication token infrastructure with support
for multiple authentication mechanisms with an emphasis on providing a
scalable single sign-on solution.
A key feature of CASA_auth_token is that its authentication tokens
contain identity information about the entity being authenticated. This
information contained in the tokens is configured on a per-service
basis. Because of this feature, we say that CASA_auth_token projects an
"Authenticated Identity".
The CASA_auth_token_apache2_2_support package contains the CASA (Common
Authentication Services Adapter) authentication token infrastructure
Apache v2.2 authentication provider module for token verification. The
module expects that users authenticate utilizing the HTTP Basic
authentication scheme and that the password utilized consist of a CASA
authentication token. Information about the authenticated identity is
environment variable.
Authors:
--------
Juan Carlos Luciani - jluciani@novell.com
%package -n CASA_auth_token_server-devel
Summary: Novell CASA Authentication Token Server Development Files
Group: Development/Libraries/C and C++
Requires: CASA-devel CASA_auth_token_server CASA_auth_token_jaas_support CASA_auth_token_pam_support CASA_auth_token_apache2_2_support CASA_auth_token_svc
%description -n CASA_auth_token_server-devel
CASA_auth_token is an authentication token infrastructure with support
for multiple authentication mechanisms with an emphasis on providing a
scalable single sign-on solution.
A key feature of CASA_auth_token is that its authentication tokens
contain identity information about the entity being authenticated. This
information contained in the tokens is configured on a per-service
basis. Because of this feature, we say that CASA_auth_token projects an
"Authenticated Identity".
The CASA_auth_token_server-devel package contains the files necessary for the
development of server applications that utilize the CASA (Common
Authentication Service Adapter) authentication token infrastructure for
authentication.
Authors:
--------
Juan Carlos Luciani - jluciani@novell.com
%prep
%setup -q
#%patch
%if %{_lib} == "lib64"
%define binsource bin64
%else
%define binsource bin
%endif
%build
export PATH=.:$PATH:/usr/%_lib/qt3/bin
%if %suse_version > 1000
export CFLAGS="$CFLAGS $RPM_OPT_FLAGS -fstack-protector"
%endif
./autogen.sh
make
%install
export NO_BRP_CHECK_BYTECODE_VERSION="true"
## Prime the file system ##
install -d %{buildroot}%{prefix}
install -d %{buildroot}%{prefix}/bin
install -d %{buildroot}%{prefix}/sbin
install -d %{buildroot}%{prefix}/%{_lib}
install -d %{buildroot}%{prefix}/%{_lib}/CASA
install -d %{buildroot}%{prefix}/%{_lib}/CASA/authtoken
install -d %{buildroot}/%{_lib}/security
install -d %{buildroot}%{prefix}/include
install -d %{buildroot}/etc/init.d
install -d %{buildroot}/etc/ld.so.conf.d
install -d %{buildroot}/var
install -d %{buildroot}/var/lib
install -d -m 755 %{buildroot}/var/lib/CASA
install -d -m 755 %{buildroot}/var/lib/CASA/authtoken
install -d -m 755 %{buildroot}/var/lib/CASA/authtoken/validate
install -d -m 755 %{buildroot}/etc/CASA
install -d -m 755 %{buildroot}/etc/CASA/authtoken
install -d -m 755 %{buildroot}/etc/CASA/authtoken/validate
install -d -m 755 %{buildroot}/etc/CASA/authtoken/modules
## CASA_auth_token_server ##
# Libs
install -m 755 %{_lib}/%{cfg}/libcasa_s_authtoken.so %{buildroot}%{prefix}/%{_lib}/libcasa_s_authtoken.so.%{bldno}
install -m 755 %{_lib}/%{cfg}/casa_iden_token.so %{buildroot}%{prefix}/%{_lib}/CASA/authtoken/casa_iden_token.so.%{bldno}
install -m 755 %{_lib}/%{cfg}/libcasa_c_ipc.so %{buildroot}%{prefix}/%{_lib}/libcasa_c_ipc.so.%{bldno}
install -m 755 %{_lib}/%{cfg}/libcasa_s_ipc.so %{buildroot}%{prefix}/%{_lib}/libcasa_s_ipc.so.%{bldno}
# Symbolic Links
ln -sf casa_iden_token.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/CASA/authtoken/casa_iden_token.so
ln -sf casa_iden_token.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/CASA/authtoken/casa_iden_token.so.1
# Bins
install -m 755 bin/%{cfg}/CasaAuthtokenValidateD %{buildroot}%{prefix}/bin/casa_atvd
# Others
install -m 644 %{_lib}/%{cfg}/CasaIdentityToken.conf %{buildroot}/etc/CASA/authtoken/modules/CasaIdentityToken.conf
install -m 755 server/AuthTokenValidate/Svc/linux/CasaAuthtokenValidateD %{buildroot}/etc/init.d/casa_atvd
install -m 750 server/AuthTokenValidate/Svc/linux/envvars %{buildroot}/etc/CASA/authtoken/validate/
ln -sf casa_atvd %{buildroot}%{prefix}/sbin/rccasa_atvd
## CASA_auth_token_pam_support ##
# Libs
install -m 755 %{_lib}/%{cfg}/pam_casaauthtok.so %{buildroot}/%{_lib}/security/pam_casaauthtok.so
## CASA_auth_token_apache2_2_support ##
# Libs
install -m 755 %{_lib}/%{cfg}/mod_authn_casa.so %{buildroot}%{prefix}/%{_lib}/mod_authn_casa.so.%{bldno}
## CASA_auth_token_server-devel ##
# Header Files
install -m 644 include/casa_s_authtoken.h %{buildroot}%{prefix}/include
install -m 644 include/casa_c_ipc.h %{buildroot}%{prefix}/include
install -m 644 include/casa_s_ipc.h %{buildroot}%{prefix}/include
# Symbolic Links for CASA_auth_token_server files
ln -sf libcasa_s_authtoken.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/libcasa_s_authtoken.so
ln -sf libcasa_s_authtoken.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/libcasa_s_authtoken.so.1
ln -sf libcasa_c_ipc.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/libcasa_c_ipc.so
ln -sf libcasa_c_ipc.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/libcasa_c_ipc.so.1
ln -sf libcasa_s_ipc.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/libcasa_s_ipc.so
ln -sf libcasa_s_ipc.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/libcasa_s_ipc.so.1
# Symbolic Links for CASA_auth_token_apache2_2_support files
ln -sf mod_authn_casa.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/mod_authn_casa.so
ln -sf mod_authn_casa.so.%{bldno} %{buildroot}%{prefix}/%{_lib}/mod_authn_casa.so.1
%clean
rm -rf $RPM_BUILD_ROOT
## CASA_auth_token_server ##
%pre
# Do necessary user and group administration
group_present=`getent group | grep ^casaauth`
if [ -z "$group_present" ] ; then
/usr/sbin/groupadd -r casaauth
fi
user_present=`getent passwd | grep ^casaatvd`
if [ -z "$user_present" ] ; then
/usr/sbin/useradd -c "casa_atvd System User" -s /bin/false -r -d /var/lib/CASA/authtoken/validate -g casaauth casaatvd 2> /dev/null || :
fi
%post
/sbin/ldconfig
# Install casa_atvd init script, set it to start by default.
%{fillup_and_insserv casa_atvd}
%preun
%stop_on_removal casa_atvd
%postun
%restart_on_update casa_atvd
%insserv_cleanup
/sbin/ldconfig
# Do not do anything else if this is an upgrade
if test "$1" == 1; then
exit 0
fi
# Delete the casaatvd user
userdel casaatvd
# Delete the var files
rm -rf /var/lib/CASA/authtoken/validate
%files
%defattr(-,root,root)
%dir %{prefix}/%{_lib}/CASA
%dir %{prefix}/%{_lib}/CASA/authtoken
%dir /var/lib/CASA
%dir /var/lib/CASA/authtoken
%dir %attr(-, casaatvd, casaauth) /var/lib/CASA/authtoken/validate
%dir /etc/CASA
%dir /etc/CASA/authtoken
%dir /etc/CASA/authtoken/validate
%dir /etc/CASA/authtoken/modules
%{prefix}/%{_lib}/libcasa_s_authtoken.so.%{bldno}
%{prefix}/%{_lib}/CASA/authtoken/casa_iden_token.so.%{bldno}
%{prefix}/%{_lib}/CASA/authtoken/casa_iden_token.so
%{prefix}/%{_lib}/CASA/authtoken/casa_iden_token.so.1
%{prefix}/%{_lib}/libcasa_c_ipc.so.%{bldno}
%{prefix}/%{_lib}/libcasa_s_ipc.so.%{bldno}
%{prefix}/bin/casa_atvd
%config /etc/CASA/authtoken/validate/envvars
%config /etc/CASA/authtoken/modules/CasaIdentityToken.conf
/etc/init.d/casa_atvd
/usr/sbin/rccasa_atvd
## CASA_auth_token_pam_support ##
%pre -n CASA_auth_token_pam_support
# Nothing to do in this pre script
%post -n CASA_auth_token_pam_support
/sbin/ldconfig
%preun -n CASA_auth_token_pam_support
# Nothing to do in this preun script
%postun -n CASA_auth_token_pam_support
/sbin/ldconfig
%files -n CASA_auth_token_pam_support
%defattr(-,root,root)
%dir /%{_lib}/security
/%{_lib}/security/pam_casaauthtok.so
## CASA_auth_token_apache2_2_support ##
%pre -n CASA_auth_token_apache2_2_support
# Nothing to do in this pre script
%post -n CASA_auth_token_apache2_2_support
/sbin/ldconfig
%preun -n CASA_auth_token_apache2_2_support
# Nothing to do in this preun script
%postun -n CASA_auth_token_apache2_2_support
/sbin/ldconfig
%files -n CASA_auth_token_apache2_2_support
%defattr(-,root,root)
%{prefix}/%{_lib}/mod_authn_casa.so.%{bldno}
## CASA_auth_token_server-devel ##
%pre -n CASA_auth_token_server-devel
# Nothing to do in this pre script
%post -n CASA_auth_token_server-devel
# Nothing to do in this post script
%preun -n CASA_auth_token_server-devel
# Nothing to do in this preun script
%postun -n CASA_auth_token_server-devel
# Nothing to do in this postun script
%files -n CASA_auth_token_server-devel
%defattr(-,root,root)
%{prefix}/include/casa_s_authtoken.h
%{prefix}/include/casa_c_ipc.h
%{prefix}/include/casa_s_ipc.h
%{prefix}/%{_lib}/libcasa_s_authtoken.so
%{prefix}/%{_lib}/libcasa_s_authtoken.so.1
%{prefix}/%{_lib}/libcasa_c_ipc.so
%{prefix}/%{_lib}/libcasa_c_ipc.so.1
%{prefix}/%{_lib}/libcasa_s_ipc.so
%{prefix}/%{_lib}/libcasa_s_ipc.so.1
%{prefix}/%{_lib}/mod_authn_casa.so
%{prefix}/%{_lib}/mod_authn_casa.so.1
%changelog -n CASA_auth_token_server

View File

@ -0,0 +1,72 @@
#######################################################################
#
# 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 =
EXTRA_DIST = CASA_auth_token_server.changes CASA_auth_token_server.spec.in
RPM_FILE = $(PACKAGE)-$(VERSION)-$(RELEASE).$(target_cpu).rpm
#SRPM_FILE = $(PACKAGE)-$(VERSION)-$(RELEASE).src.rpm
SRPM_FILE = $(PACKAGE)-$(VERSION)*.src.rpm
SPEC_FILE = CASA_auth_token_server.spec
.PHONY: package package-clean package-install package-uninstall casa
#all: $(RPM_FILE)
package: $(RPM_FILE)
all clean:
$(RPM_FILE):
cd $(top_srcdir); make dist-bzip2
rm -rf RPM
mkdir RPM
echo %_topdir `pwd`/RPM > $(HOME)/.rpmmacros
mkdir -p RPM/BUILD
mkdir -p RPM/RPMS
mkdir -p RPM/SOURCES
mkdir -p RPM/SPECS
mkdir -p RPM/SRPMS
cp $(SPEC_FILE) RPM/SPECS
cp $(top_srcdir)/$(PACKAGE)-*.tar.bz2 RPM/SOURCES
mv $(top_srcdir)/$(PACKAGE)-$(VERSION).tar.bz2 $(PACKAGE)-$(VERSION).tar.bz2
rpmbuild -ba -v -vv --target=$(target_triplet) RPM/SPECS/$(SPEC_FILE)
cp RPM/RPMS/*/*.rpm .
cp RPM/SRPMS/$(SRPM_FILE) .
package-install: package
su -c "rpm -Uvh $(RPM_FILE)"
package-uninstall:
su -c "rpm -e $(PACKAGE)"
package-clean clean-local:
rm -rf *.rpm RPM *.bz2
distclean-local: package-clean
rm -f Makefile $(SPEC_FILE)
maintainer-clean-local:
rm -f Makefile.in

View File

@ -0,0 +1,41 @@
#######################################################################
#
# 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 LINUX
SUBDIRS = $(TARGET_OS)
else
SUBDIRS =
endif
DIST_SUBDIRS = linux
CFILES =
EXTRA_DIST = $(CFILES)
.PHONY: package package-clean package-install package-uninstall
package package-clean package-install package-uninstall:
$(MAKE) -C $(TARGET_OS) $@
maintainer-clean-local:
rm -f Makefile.in

View File

@ -0,0 +1,103 @@
/***********************************************************************
*
* 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>
*
***********************************************************************/
/***********************************************************************
*
* README for IpcLibs
*
***********************************************************************/
INTRODUCTION
IpcLibs provides an IPC infrastructure that can be linked into client and server
applications.
IpcLibs provides IPC communications over TCP or DOMAIN sockets. It does this in a scalable
and un-serialized manner. The infrastructure can make use of multiple communication channels
between a client and a server and is capabled of concurrently serving multiple requests over
the different channels.
The IpcLib APIs are very simple to utilize and support multi-threaded applications.
SERVER APPLICATION PROGRAMMING NOTES
The IPC API for server applications is defined in casa_s_ipc.h. This API is provided by
libcasa_s_ipc.so.
To utilize the IPC server services, an application must first initialize the infrastructure by
calling IpcServerInit() which is then followed by the desired IpcServerSetXXAddress() call.
After the Ipc server is initialized and the server address is set, then the application calls
IpcServerStart() to start the engine (This causes the engine to start to accept connections and
receive requests from clients).
To start servicing requests, the application executesIpcServerGetRequest(); this calls blocks until
a request is ready to be serviced at which time it returns with an ID which is associated with the
request that needs to be serviced. The returned ID is then used by the application to retrieve the
request data via the IpcServerGetRequestData(), once the application processes the request, it
completes it by executing IpcServerCompleteRequest() with the ID and any data that it may want to
send back to the client.
Note that a server application can call IpcServerGetRequest() from multiple threads to make itself
more scalable.
For an example server application that utilizes the IPC API for servers, see file
linux/server/test/testServer.c.
CLIENT APPLICATION PROGRAMMING NOTES
The IPC API for client applications is defined in casa_c_ipc.h. This API is provided by
libcasa_c_ipc.so.
To utilize the IPC client services, an application must first initialize the infrastructure by
calling IpcClientInit(). Once the IPC client is initialized, then the application needs to open
endpoints for the servers that it wishes to submit requests. Endpoints are opened by calling the
appropriate IpcClientOpenXXRemoteEndPoint() with information about the server listen address.
IpcClientOpenXXRemoteEndpoint() calls return a handles that are associated with the opened
endpoints. This endpoint handles are then utilized by the application to specify the target of
IPC requests.
To submit a request to a particular endpoint, the application executes IpcClientSubmitReq() with
the endpoint handle and the request data. Calls to IpcClientSubmitReq() block until the requests
is processed by the server at which time it returns the reply data.
For an example client application that utilizes the IPC API for clients, see file
linux/client/test/testClient.c.
SECURITY CONSIDERATIONS
IpcLibs does not provide any security features beyond what is provided by the protocol stacks for
tcp/ip and Domain sockets communications.
By leveraging the File System Access Control features, you can scope communications that occur over
Domain sockets to specific or groups of users.

View File

@ -0,0 +1,14 @@
/***********************************************************************
*
* TODO for IpcLibs
*
***********************************************************************/
INTRODUCTION
This file contains a list of the items still outstanding for IpcLibs.
OUTSTANDING ITEMS
- Add APIs to allow for the senging of fragmented request and reply data.

View File

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

View File

@ -0,0 +1,126 @@
#######################################################################
#
# 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
DEFINES = -DDBG
else
TARGET_CFG = Release
DEFINES = -DNDEBUG
endif
# Override the link setting for C++
LINK = g++
SUBDIRS =
DIST_SUBDIRS =
ROOT = ../../../..
LIBDIR = $(ROOT)/$(LIB)
# handle Mono secondary dependencies
export MONO_PATH := $(MONO_PATH)
COMMON = ../common
CLIENT = .
MODULE_NAME = libcasa_c_ipc
MODULE_EXT = so
CFILES =
CPPFILES = cchannel.cpp \
clientreq.cpp \
remoteendpoint.cpp \
client.cpp
COMMONCPPFILES = channelproto.cpp
CSFILES_CSC :=
INCLUDES = -I. -I.. -I../common -I../../../../include
RESOURCES =
if LIB64
DEFINES += -D_LIB64
endif
CFLAGS += -Wno-format-extra-args -fno-strict-aliasing -fshort-wchar $(INCLUDES) $(DEFINES)
CPPFLAGS += -Wno-format-extra-args -fno-strict-aliasing -fshort-wchar -fPIC $(INCLUDES) $(DEFINES) $(RPM_OPT_FLAGS)
LIBS = -lpthread
LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT)
OBJDIR = ./$(TARGET_CFG)/$(LIB)
OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) $(addprefix $(OBJDIR)/, $(COMMONCPPFILES:%.cpp=%.o)) $(addprefix $(OBJDIR)/, $(CPPFILES:%.cpp=%.o))
EXTRA_DIST = $(CFILES) $(CPPFILES) *.h
CUR_DIR := $(shell pwd)
all: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT)
#
# Pattern based rules.
#
vpath %.c $(CLIENT) $(COMMON)
vpath %.cpp $(CLIENT) $(COMMON)
$(OBJDIR)/%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
$(OBJDIR)/%.o: %.cpp
$(CC) -c $(CPPFLAGS) -o $@ $<
$(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT): $(OBJDIR) $(OBJS)
@echo [======== Linking $@ ========]
$(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS)
cp -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(LIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT)
$(OBJDIR):
[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
[ -d $(LIBDIR) ] || mkdir -p $(LIBDIR)
[ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(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

View File

@ -0,0 +1,949 @@
/***********************************************************************
*
* 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 "ipcint.h"
#include "cchannel.h"
#include "clientreq.h"
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
//
// Socket Mapping definitions
//
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define LINGER struct linger
#define SOCKADDR_IN struct sockaddr_in
#define closesocket close
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//
// Object Counters
//
unsigned long numCChannelObjects = 0;
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//++=======================================================================
CChannel::CChannel(
struct sockaddr_in *pRemoteAddress) :
m_state (State_Uninitialized),
m_socket (INVALID_SOCKET),
m_reqIdAllocator (1)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "CChannel::CChannel(TcpSocket)- Start, Obj = %08X\n", this);
// Use Tcp socket
m_useTcpSocket = true;
// Save a copy of the remote address
memcpy(&m_remoteAddrIn, pRemoteAddress, sizeof(struct sockaddr_in));
// Initialize the mutex
if (pthread_mutex_init(&m_mutex, NULL) != 0)
{
DbgTrace(0, "CChannel::CChannel- Mutex initialization failed\n", 0);
// Throw exception
throw bad_alloc();
}
// Increment the object count
InterlockedIncrement(&numCChannelObjects);
DbgTrace(1, "CChannel::CChannel(TcpSocket)- End\n", 0);
} /*-- CChannel::CChannel(TcpSocket) --*/
//++=======================================================================
CChannel::CChannel(
struct sockaddr_un *pRemoteAddress) :
m_state (State_Uninitialized),
m_socket (INVALID_SOCKET),
m_reqIdAllocator (1)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "CChannel::CChannel(DomainSocket)- Start, Obj = %08X\n", this);
// Do not use Tcp socket
m_useTcpSocket = false;
// Save a copy of the remote address
memcpy(&m_remoteAddrUn, pRemoteAddress, sizeof(struct sockaddr_un));
// Initialize the mutex
if (pthread_mutex_init(&m_mutex, NULL) != 0)
{
DbgTrace(0, "CChannel::CChannel- Mutex initialization failed\n", 0);
// Throw exception
throw bad_alloc();
}
// Increment the object count
InterlockedIncrement(&numCChannelObjects);
DbgTrace(1, "CChannel::CChannel(DomainSocket)- End\n", 0);
} /*-- CChannel::CChannel(DomainSocket) --*/
//++=======================================================================
CChannel::~CChannel(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "CChannel::~CChannel- Start, Obj = %08X\n", this);
// Cleanup resources allocated for the object
pthread_mutex_destroy(&m_mutex);
// Free connection socket if necessary
if (m_socket != INVALID_SOCKET)
{
shutdown(m_socket, SHUT_RDWR);
struct linger linger_opt = {1, 15};
setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt));
closesocket(m_socket);
}
// Decrement the object count
InterlockedDecrement(&numCChannelObjects);
DbgTrace(1, "CChannel::~CChannel- End\n", 0);
} /*-- CChannel::~CChannel() --*/
//++=======================================================================
void
CChannel::openSocket(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "CChannel::openSocket- Start\n", 0);
// Open a domain socket if not using Tcp
if (m_useTcpSocket == false)
m_socket = socket(PF_UNIX, SOCK_STREAM, 0);
else
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
DbgTrace(1, "CChannel::openSocket- End\n", 0);
} /*-- CChannel::openSocket() --*/
//++=======================================================================
int
CChannel::connectSocket(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus;
DbgTrace(1, "CChannel::connectSocket- Start\n", 0);
// Proceed based on whether or not we need
// to use Tcp sockets.
if (m_useTcpSocket)
{
struct sockaddr_in localAddr = {0};
// Setup the address structure
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
// Perform bind operation
retStatus = bind(m_socket,
(const sockaddr*) &localAddr,
sizeof(struct sockaddr_in));
if (!retStatus)
{
// Perform connect operation
retStatus = connect(m_socket,
(struct sockaddr*) &m_remoteAddrIn,
sizeof(struct sockaddr_in));
if (retStatus == SOCKET_ERROR)
{
DbgTrace(0, "CChannel::connectSocket- Connection creation failed, error = %d\n", errno);
}
}
else
{
DbgTrace(0, "CChannel::connectSocket- Unable to bind socket, error = %d", errno);
}
}
else
{
// Perform connect operation
retStatus = connect(m_socket,
(struct sockaddr*) &m_remoteAddrUn,
sizeof(m_remoteAddrUn.sun_family) + strlen(m_remoteAddrUn.sun_path));
if (retStatus == SOCKET_ERROR)
{
DbgTrace(0, "CChannel::connectSocket- Connection creation failed, error = %d\n", errno);
}
}
DbgTrace(1, "CChannel::connectSocket- End, status = %08X\n", retStatus);
return retStatus;
} /*-- CChannel::connectSocket() --*/
//++=======================================================================
int
CChannel::init(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus = -1;
SmartCChannel *pSmartCChannel = NULL;
DbgTrace(1, "CChannel::init- Start, Obj = %08X\n", this);
// Verify the state of the object
if (m_state == State_Uninitialized)
{
openSocket();
if (m_socket != INVALID_SOCKET)
{
if (connectSocket() != SOCKET_ERROR)
{
// Advance the object state
m_state = State_Connected;
// Launch a thread to service the channel connection
try {
// Create a SmartCChannel object to make sure that the object
// does not get deleted prematurely.
pSmartCChannel = new SmartCChannel(this);
// Create the channel connection thread
pthread_t thread;
int threadCreateStatus = pthread_create(&thread,
NULL,
(void*(*)(void*))CChannel::connectionThread,
pSmartCChannel);
if (threadCreateStatus == 0)
{
// We succeeded
retStatus = 0;
}
else
{
DbgTrace(0, "CChannel::init- Unable to create channel connection thread, error = %08X\n", threadCreateStatus);
}
}
catch (...) {
DbgTrace(0, "CChannel::init- Exception caught creating smart pointer\n", 0);
}
}
else
{
DbgTrace(0, "CChannel::init- Connection creation failed, error = %d\n", errno);
}
}
else
{
DbgTrace(0, "CChannel::init- Unable to open socket, error = %d\n", errno);
}
}
else
{
DbgTrace(0, "CChannel::init- invalid state, state = %d\n", m_state);
}
// Deal with initialization failures
if (retStatus)
{
// Adjust the object state
m_state = State_FailedInitialization;
// Free SmartCChannel just in case
delete pSmartCChannel;
}
DbgTrace(1, "CChannel::init- End, status = %08X\n", retStatus);
return retStatus;
} /*-- CChannel::init() --*/
//++=======================================================================
void*
CChannel::connectionThread(
SmartPtr<CChannel> *pSmartCChannel)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
CChannel *pCChannel = *pSmartCChannel;
bool doneReceivingData = false;
unsigned long bytesReceived;
uint32_t reqId;
int payloadLength;
unsigned long totalPayloadBytesReceived = 0;
char reqDataPktHdr[ReqDataPktHdrTemplate.length()];
char *pRecvBuff;
RCMapIter iter;
ClientReq *pClientReq;
DbgTrace(1, "CChannel::connectionThread- Start, Obj = %08X\n", pCChannel);
// Set the thread in the detached state so that it is cleaned up when it exits
pthread_detach(pthread_self());
// Check that we are still connected
if (pCChannel->m_state == State_Connected)
{
// Receive and process channel data
while (!doneReceivingData)
{
DbgTrace(2, "CChannel::connectionThread- Receive Loop, Obj = %08X\n", pCChannel);
// Receive the ReqDataPktHdr. Note, if we add other packet types and if the
// packet types have different header lengths, then we will need to modify
// this code to first receive the packet type and then receive the rest
// of the header based on type.
while (1)
{
bytesReceived = recv(pCChannel->m_socket,
reqDataPktHdr,
sizeof(reqDataPktHdr),
MSG_WAITALL);
if (bytesReceived == SOCKET_ERROR
&& errno == EINTR)
{
continue;
}
break;
}
if (bytesReceived != SOCKET_ERROR)
{
// Check if the connection was terminated
if (bytesReceived == sizeof(reqDataPktHdr))
{
// Get the payload length
if (ChannelProto::getReqIdAndPayloadLength(reqDataPktHdr,
sizeof(reqDataPktHdr),
&reqId,
&payloadLength))
{
// Procced based on the packet type
switch (ChannelProto::getPktType(*reqDataPktHdr))
{
case ChannelProto::ReqDataCarrierPacketType:
DbgTrace(2, "CChannel::connectionThread- Processing Request Data Packet, Obj = %08X\n", pCChannel);
// Allocate a buffer big enough to receive the payload. Allow space to NULL terminate.
pRecvBuff = (char*) malloc(payloadLength + 1);
if (pRecvBuff != NULL)
{
pRecvBuff[payloadLength] = '\0';
// Buffer allocated, receive the request payload.
while (1)
{
bytesReceived = recv(pCChannel->m_socket,
pRecvBuff,
payloadLength,
MSG_WAITALL);
if (bytesReceived == SOCKET_ERROR
&& errno == EINTR)
{
continue;
}
break;
}
if (bytesReceived != SOCKET_ERROR)
{
// Verify that we received all of the payload
if (bytesReceived == payloadLength)
{
// Received all of the payload data
totalPayloadBytesReceived += bytesReceived;
// Acquire exclusive access to the CChannel object
pthread_mutex_lock(&pCChannel->m_mutex);
// Find the appropriate ClientReq object in the ClientReqMap using
// the reqId present in the Req Data Packet Header.
iter = pCChannel->m_rcMap.find(reqId);
if (iter != pCChannel->m_rcMap.end())
{
// Object was found in the map, use it to process the
// request payload.
pClientReq = iter->second;
pClientReq->processServerData(pRecvBuff,
bytesReceived);
// Forget about the receive buffer
pRecvBuff = NULL;
}
else
{
DbgTrace(0, "CChannel::connectionThread- Error, did not find object in map, Obj = %08X\n", pCChannel);
}
// Release exclusive access to the CChannel object
pthread_mutex_unlock(&pCChannel->m_mutex);
}
else
{
DbgTrace(1, "CChannel::connectionThread- Connection aborted prematurely, Obj = %08X\n", pCChannel);
//DbgTrace(0, "CChannel::connectionThread- 1Connection aborted prematurely, Obj = %08X\n", pCChannel);
//DbgTrace(0, "CChannel::connectionThread- 1bytesReceived = %d\n", bytesReceived);
//DbgTrace(0, "CChannel::connectionThread- 1payloadLength = %d\n", payloadLength);
//DbgTrace(0, "CChannel::connectionThread- 1errno = %d\n", errno);
//printf("bytesReceived = %d, payloadLength = %d\n", bytesReceived, payloadLength);
//printf("CChannel::connectionThread- 1Connection aborted prematurely, Obj = %08X\n", pCChannel);
doneReceivingData = true;
}
}
else
{
DbgTrace(1, "CChannel::connectionThread- Connection aborted prematurely, Obj = %08X\n", pCChannel);
//DbgTrace(0, "CChannel::connectionThread- 2Connection aborted prematurely, Obj = %08X\n", pCChannel);
//DbgTrace(0, "CChannel::connectionThread- 2errno = %d\n", errno);
//printf("Socket error = %d\n", errno);
//printf("CChannel::connectionThread- 2Connection aborted prematurely, Obj = %08X\n", pCChannel);
doneReceivingData = true;
}
// Free receive buffer if necessary
if (pRecvBuff)
delete[] pRecvBuff;
}
else
{
DbgTrace(0, "CChannel::connectionThread- Unable to allocate receive buffer, Obj = %08X\n", pCChannel);
doneReceivingData = true;
}
break;
case ChannelProto::ReqErrorCarrierPacketType:
DbgTrace(1, "CChannel::connectionThread- Processing Request Error Packet, Obj = %08X\n", pCChannel);
// Acquire exclusive access to the CChannel object
pthread_mutex_lock(&pCChannel->m_mutex);
// Find the appropriate ClientReq object in the ClientReqMap using
// the reqId present in the Req Data Packet Header.
iter = pCChannel->m_rcMap.find(reqId);
if (iter != pCChannel->m_rcMap.end())
{
// Object was found in the map, use it to process the Request Error.
pClientReq = iter->second;
pClientReq->processError();
}
else
{
DbgTrace(0, "CChannel::connectionThread- Error, did not find object in map, Obj = %08X\n", pCChannel);
}
// Release exclusive access to the CChannel object
pthread_mutex_unlock(&pCChannel->m_mutex);
break;
default:
DbgTrace(0, "CChannel::connectionThread- Unknown Packet Type, Obj = %08X\n", pCChannel);
doneReceivingData = true;
break;
}
}
else
{
DbgTrace(1, "CChannel::connectionThread- Unable to obtain payload length, Obj = %08X\n", pCChannel);
doneReceivingData = true;
}
}
else
{
DbgTrace(1, "CChannel::connectionThread- The channel connection was terminated, Obj = %08X\n", pCChannel);
//DbgTrace(0, "CChannel::connectionThread- 3The channel connection was terminated, Obj = %08X\n", pCChannel);
//DbgTrace(0, "CChannel::connectionThread- 3bytesReceived = %d\n", bytesReceived);
//DbgTrace(0, "CChannel::connectionThread- 3expected = %d\n", ReqDataPktHdrTemplate.length());
//DbgTrace(0, "CChannel::connectionThread- 3errno = %d\n", errno);
//printf("bytesReceived = %d, expected = %d\n", bytesReceived, ReqDataPktHdrTemplate.length());
//printf("CChannel::connectionThread- 3The channel connection was terminated, Obj = %08X\n", pCChannel);
doneReceivingData = true;
}
}
else
{
DbgTrace(1, "CChannel::connectionThread- The channel connection was aborted, Obj = %08X\n", pCChannel);
//DbgTrace(0, "CChannel::connectionThread- 4The channel connection was aborted, Obj = %08X\n", pCChannel);
//DbgTrace(0, "CChannel::connectionThread- 4errno = %d\n", errno);
//printf("Socket error = %d\n", errno);
//printf("CChannel::connectionThread- 4The channel connection was aborted, Obj = %08X\n", pCChannel);
doneReceivingData = true;
}
}
}
// Acquire exclusive access to the CChannel object
pthread_mutex_lock(&pCChannel->m_mutex);
// Try to change the CChannel state to disconnected
if (pCChannel->m_state == State_Connected)
pCChannel->m_state = State_Disconnected;
// Deliver error notifications to all of the ClientReqs
// still associated with the CChannel.
if (!pCChannel->m_rcMap.empty())
{
iter = pCChannel->m_rcMap.begin();
while (iter != pCChannel->m_rcMap.end())
{
// Object was found in the map, deliver error notification
// to it.
pClientReq = iter->second;
pClientReq->processError();
// Move on to the next element in the map
iter ++;
}
}
// Release exclusive access to the CChannel object
pthread_mutex_unlock(&pCChannel->m_mutex);
// Free SmartCChannel
delete pSmartCChannel;
DbgTrace(0, "CChannel::connectionThread- End\n", 0);
// Exit
pthread_exit(NULL);
return 0; // never-reached!
} /*-- CChannel::connectionThread() --*/
//++=======================================================================
void
CChannel::closeChannel(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "CChannel::closeChannel- Start, Obj = %08X\n", this);
// Acquire CChannel mutex
pthread_mutex_lock(&m_mutex);
// Switch the socket state to closed
m_state = State_Closed;
// Check if we must close the socket
if (m_socket != INVALID_SOCKET)
{
// Socket needs to be closed, this will
// release the channel connection thread
// if it is active.
shutdown(m_socket, SHUT_RDWR);
struct linger linger_opt = {1, 15};
setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt));
closesocket(m_socket);
m_socket = INVALID_SOCKET;
}
// Release CChannel mutex
pthread_mutex_unlock(&m_mutex);
DbgTrace(1, "CChannel::closeChannel- End\n", 0);
} /*-- CChannel::closeChannel() --*/
//++=======================================================================
bool
CChannel::ok(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
bool retStatus;
DbgTrace(1, "CChannel::ok- Start, Obj = %08X\n", this);
// Return true if connected
if (m_state == State_Connected)
retStatus = true;
else
retStatus = false;
DbgTrace(1, "CChannel::ok- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- CChannel::ok() --*/
//++=======================================================================
uint32_t
CChannel::allocReqId(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
uint32_t allocatedId;
DbgTrace(1, "CChannel::allocReqId- Start, Obj = %08X\n", this);
// Perform atomic operation
allocatedId = InterlockedIncrement(&m_reqIdAllocator);
DbgTrace(1, "CChannel::allocReqId- End, allocatedId = %08X\n", allocatedId);
return allocatedId;
} /*-- CChannel::allocReqId() --*/
//++=======================================================================
int
CChannel::submitReq(
uint32_t reqId,
ClientReq &clientReq,
char *pClientData,
int clientDataLen)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus = -1;
char reqDataPktHdr[ReqDataPktHdrTemplate.length()];
struct msghdr sendmsgHdr = {0};
struct iovec ioVectors[2];
unsigned long bytesSent;
unsigned long totalBytesSent = 0;
unsigned long bytesToSend = sizeof(reqDataPktHdr) + clientDataLen;
DbgTrace(1, "CChannel::submitReq- Start, Obj = %08X\n", this);
// Acquire exclusive access to the channel object
pthread_mutex_lock(&m_mutex);
// Verify that the channel is connected
if (m_state == State_Connected)
{
// Insert the specified ClientReq into the ClientReqMap and forward the client
// data to the server.
RCIterBoolPair insertResult;
insertResult = m_rcMap.insert(make_pair(reqId, &clientReq));
if (!insertResult.second)
{
// Insertion failed
DbgTrace(0, "CChannel::submitReq- Unable to insert ClientReq into ClientReqMap, Obj = %08X\n", this);
}
else
{
// Insertion succeded, now send the request to the server.
//
// Build ReqDataHeader
if (ChannelProto::buildReqDataPktHdr(reqId,
clientDataLen,
reqDataPktHdr) == 0)
{
// Packet header was built, now sent it along with the client data to
// the server.
ioVectors[0].iov_base = reqDataPktHdr;
ioVectors[0].iov_len = sizeof(reqDataPktHdr);
ioVectors[1].iov_base = (char*) pClientData;
ioVectors[1].iov_len = clientDataLen;
sendmsgHdr.msg_iov = ioVectors;
sendmsgHdr.msg_iovlen = 2;
while (1)
{
bytesSent = sendmsg(m_socket,
&sendmsgHdr,
MSG_NOSIGNAL);
if (bytesSent == SOCKET_ERROR)
{
// Check if we were interrupted during the transfer
if (errno == EINTR)
{
// Just try again
continue;
}
// An unrecoverable error was encountered during the send operation,
// assume there was a communication failure. Close the socket to make
// sure that the connectionThread cleans up.
DbgTrace(0, "CChannel::submitReq- sendmsg error, errno = %d\n", errno);
m_state = State_Disconnected;
shutdown(m_socket, SHUT_RDWR);
struct linger linger_opt = {1, 15};
setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt));
closesocket(m_socket);
m_socket = INVALID_SOCKET;
break;
}
else
{
// Account for the bytes sent
totalBytesSent += bytesSent;
// Check if we are done sending all of the data
if (totalBytesSent >= bytesToSend)
{
// We are done
break;
}
else
{
// Adjust the ioVector structure to send data not yet sent
if (totalBytesSent >= sizeof(reqDataPktHdr))
{
// The packet header was sent, use only one ioVector.
int clientDataAlreadySent = totalBytesSent - sizeof(reqDataPktHdr);
ioVectors[0].iov_base = (char*) pClientData + clientDataAlreadySent;
ioVectors[0].iov_len = clientDataLen - clientDataAlreadySent;
sendmsgHdr.msg_iov = ioVectors;
sendmsgHdr.msg_iovlen = 1;
}
else
{
// Not all of the packet header was sent, use two ioVectors.
ioVectors[0].iov_base = (char*) reqDataPktHdr + totalBytesSent;
ioVectors[0].iov_len = sizeof(reqDataPktHdr) - totalBytesSent;
ioVectors[1].iov_base = (char*) pClientData;
ioVectors[1].iov_len = clientDataLen;
sendmsgHdr.msg_iov = ioVectors;
sendmsgHdr.msg_iovlen = 2;
}
}
}
}
// Return success even if the send failed to allow things to be cleaned up
// by the connectionThread routine.
retStatus = 0;
}
else
{
DbgTrace(0, "CChannel::submitReq- Error building Req Data Pkt Header, Obj = %08X\n", this);
// Remove ClientReq from the ClientReqMap
RCMapIter iter = m_rcMap.find(reqId);
if (iter != m_rcMap.end())
{
// Object was found in the map, remove it.
m_rcMap.erase(iter);
}
else
{
DbgTrace(0, "CChannel::submitReq- Error, did not find object in map to remove\n", 0);
}
}
}
}
else
{
DbgTrace(1, "CChannel::submitReq- Channel not connected, state = %08X\n", m_state);
}
// Release exclusive access to the channel object
pthread_mutex_unlock(&m_mutex);
DbgTrace(1, "CChannel::submitReq- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- CChannel::submitReq() --*/
//++=======================================================================
void
CChannel::removeReq(
uint32_t reqId)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "CChannel::removeReq- Start, Obj = %08X\n", this);
// Acquire exclusive access to the channel object
pthread_mutex_lock(&m_mutex);
// Try to find the ClientReq in the ClientReqMap using the reqId
RCMapIter iter = m_rcMap.find(reqId);
if (iter != m_rcMap.end())
{
// Object was found in the map, remove it.
m_rcMap.erase(iter);
}
else
{
DbgTrace(0, "CChannel::removeReq- Error, did not find object in map\n", 0);
}
// Release exclusive access to the channel object
pthread_mutex_unlock(&m_mutex);
DbgTrace(1, "CChannel::removeReq- End\n", 0);
} /*-- CChannel::removeReq() --*/
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,274 @@
/***********************************************************************
*
* 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 _CCHANNEL_
#define _CCHANNEL_
//===[ Include files ]=====================================================
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//===[ Type definitions ]==================================================
// Forward reference
class ClientReq;
//
// CChannel Class Definition
//
class CChannel : public ObjRef
{
// Object State
enum ChannelStates
{
State_Uninitialized = 1,
State_FailedInitialization,
State_Connected,
State_Disconnected,
State_Closed
};
ChannelStates m_state;
// Connection socket
int m_socket;
// Connection addresses
struct sockaddr_in m_remoteAddrIn;
struct sockaddr_un m_remoteAddrUn;
bool m_useTcpSocket;
// ReqId Allocator
uint32_t m_reqIdAllocator;
// Synchronization variables
pthread_mutex_t m_mutex;
//
// Client Request Map - This map contains all of the active ClientReq objects.
// The key used to obtain ClientReq object in the map
// is the Request Id.
//
typedef map<uint32_t, ClientReq*> RCMap;
typedef RCMap::iterator RCMapIter;
typedef pair<RCMapIter, bool> RCIterBoolPair;
RCMap m_rcMap;
//
// Service connection thread procedure
//
// Parameters:
// pSmartCChannel (input) -
// Pointer to SmartPtr<CChannel> object.
//
// Abstract: Thread in charge of servicing channel connection.
//
// Returns: Nothing.
//
static void* connectionThread(SmartPtr<CChannel> *pSmartCChannel);
//
// Open socket routine
//
// Parameters: None.
//
// Abstract: Opens CChannel object socket.
//
// Returns: Nothing.
//
void openSocket(void);
//
// Connect socket routine
//
// Parameters: None.
//
// Abstract: Connects the CChannel object socket.
//
// Returns: Socket connect operation return status.
//
int connectSocket(void);
public:
//
// Constructor
//
// Parameters:
// remoteAddress (input) -
// Reference to sockaddr_in structure containing the remote
// endpoint address.
//
// Abstract: Constructs CChannel object.
//
// Returns: Nothing.
//
CChannel(struct sockaddr_in *remoteAddress);
//
// Constructor
//
// Parameters:
// remoteAddress (input) -
// Reference to sockaddr_un structure containing the remote
// endpoint address.
//
// Abstract: Constructs CChannel object.
//
// Returns: Nothing.
//
CChannel(struct sockaddr_un *remoteAddress);
//
// Destructor
~CChannel(void);
//
// Initialization routine
//
// Parameters: None.
//
// Abstract: Initializes CChannel object.
//
// Returns: 0 if successful.
//
int init(void);
//
// Close channel routine
//
// Parameters: None.
//
// Abstract: Closes the channel.
//
// Returns: Nothing.
//
void closeChannel(void);
//
// Check channel status routine.
//
// Parameters: None.
//
// Abstract: Checks if the channel status is OK
//
// Returns: True if the channel status is OK.
//
bool ok(void);
//
// Allocate Request Id routine
//
// Parameters: None.
//
// Abstract: Closes the channel.
//
// Returns: Allocated Request Id.
//
uint32_t allocReqId(void);
//
// Submit Request routine
//
// Parameters:
// reqId (input) -
// Id of the Request.
//
// clientReq (input) -
// Reference to ClientReq object.
//
// pClientData (input) -
// Pointer to client data that must be sent to
// the server. Buffer is NEVER released by the
// procedure.
//
// clientDataLen (input) -
// Length of the client data.
//
// Abstract: Submits a Request.
//
// Returns: 0 if successful.
//
int submitReq(uint32_t reqId,
ClientReq &clientReq,
char *pClientData,
int clientDataLen);
//
// Remove Request routine
//
// Parameters:
// reqId (input) -
// Id of the Request.
//
// Abstract: Removes a Request from the channel.
//
// Returns: Nothing.
//
void removeReq(uint32_t reqId);
//
// Send Data routine
//
// Parameters:
// reqId (input) -
// Id of the Request.
//
// pClientData (input) -
// Pointer to client data that must be sent to
// the server. Buffer is NEVER released
// by the procedure.
//
// clientDataLen (input) -
// Length of the client data.
//
//
// Abstract: Sends data to the server for a previously
// submitted Request.
//
// Returns: 0 if successful.
//
int sendData(uint32_t reqId,
char *pClientData,
int clientDataLen);
};
typedef SmartPtr<CChannel> SmartCChannel;
//===[ Function prototypes ]===============================================
#endif // _CCHANNEL_
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,628 @@
/***********************************************************************
*
* 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 "ipcint.h"
extern "C" {
#include "casa_c_ipc.h"
}
#include "cchannel.h"
#include "clientreq.h"
#include "remoteendpoint.h"
//===[ External data ]=====================================================
extern
unsigned long numCChannelObjects;
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
#define DEFAULT_MAX_RPC_RETRIES 3
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
// Debug Level
int DebugLevel = 0;
bool UseSyslog = false;
// Application Name for logging purposes
char unInitialized[] = "Uninitialized";
char *pAppName = unInitialized;
// Application threaded information
bool appMultithreaded;
// Client mutex
pthread_mutex_t clientMutex;
// Mutex for interlocked operations
pthread_mutex_t interlockedMutex;
// Indicators
bool svcInitialized = false;
// Map of open remote endpoints.
//
// This map contains all of the open remote
// endpoint objects. The key used to obtain
// RemoteEndPoint objects from the map is an
// object handle.
//
typedef map<uint32_t, SmartPtr<RemoteEndPoint>*> REPMap;
typedef REPMap::iterator REPMapIter;
typedef pair<REPMapIter, bool> REPIterBoolPair;
REPMap repMap;
// RemoteEndPoint handle allocator
uint32_t remoteEndPointHandleAllocator = 1;
//++=======================================================================
extern "C"
int
IpcClientOpenUnixRemoteEndPoint(
IN char *pSocketFileName,
IN int maxRpcRetries,
INOUT uint32_t *pEndPointHandle)
//
// Arguments In: port - Server's listening port number.
//
// address - The server's IP Address. Use
// 0x7F000001 if the server is local.
//
// maxRpcRetries - Maximum number of Rpc retries that
// should be utilized when submitting
// a request to the endpoint. A value
// of zero requests that the default
// setting be utilized.
//
// Arguments Out: pEndPointHandle - Pointer to variable that will receive
// the endpoint handle.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to open a UNIX (PF_UNIX) remote endpoint.
//
// Note: The service should have been initialized before calling
// this procedure.
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "IpcClientOpenUnixRemoteEndPoint- Start\n", 0);
// Verify the input parameters
if (pSocketFileName == NULL
|| pEndPointHandle == NULL)
{
DbgTrace(0, "IpcClientOpenUnixRemoteEndPoint- Invalid parameter\n", 0);
goto exit;
}
// Verify that we have been initialized
if (svcInitialized)
{
// Set the default max rpc retry value if necessary
if (maxRpcRetries == 0)
maxRpcRetries = DEFAULT_MAX_RPC_RETRIES;
// Acquire our mutex
pthread_mutex_lock(&clientMutex);
try {
// Instantiate a RemoteEndPoint object and keep track of it
// with a smart pointer.
SmartRemoteEndPoint *pSmartRemoteEndPoint = new SmartRemoteEndPoint(new RemoteEndPoint(appMultithreaded,
maxRpcRetries,
pSocketFileName));
// Allocate a handle for the endpoint
uint32_t handle = remoteEndPointHandleAllocator ++;
// Insert the new RemoteEndPoint into the REP map
REPIterBoolPair insertResult;
insertResult = repMap.insert(make_pair(handle, pSmartRemoteEndPoint));
if (!insertResult.second)
{
// Insertion failed
DbgTrace(0, "IpcClientOpenUnixRemoteEndPoint- Unable to insert RemoteEndPoint into REP\n", 0);
delete pSmartRemoteEndPoint;
}
else
{
// RemoteEndPoint inserted in the REP map, success.
*pEndPointHandle = handle;
retStatus = 0;
}
} catch (...) {
DbgTrace(0, "IpcClientOpenUnixRemoteEndPoint- Exception caught\n", 0);
}
pthread_mutex_unlock(&clientMutex);
}
else
{
DbgTrace(0, "IpcClientOpenUnixRemoteEndPoint- Not initialized\n", 0);
}
exit:
DbgTrace(1, "IpcClientOpenUnixRemoteEndPoint- End, status = %08X\n", retStatus);
return retStatus;
}
//++=======================================================================
extern "C"
int
IpcClientOpenInetRemoteEndPoint(
IN unsigned short int port,
IN uint32_t address,
IN int maxRpcRetries,
INOUT uint32_t *pEndPointHandle)
//
// Arguments In: port - Server's listening port number.
//
// address - The server's IP Address. Use
// 0x7F000001 if the server is local.
//
// maxRpcRetries - Maximum number of Rpc retries that
// should be utilized when submitting
// a request to the endpoint. A value
// of zero requests that the default
// setting be utilized.
//
// Arguments Out: pEndPointHandle - Pointer to variable that will receive
// the endpoint handle.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to open a TCP (AF_INET) remote endpoint.
//
// Note: The service should have been initialized before calling
// this procedure.
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "IpcClientOpenInetRemoteEndPoint- Start\n", 0);
// Verify the input parameters
if (pEndPointHandle == NULL)
{
DbgTrace(0, "IpcClientOpenInetRemoteEndPoint- Invalid parameter\n", 0);
goto exit;
}
// Verify that we have been initialized
if (svcInitialized)
{
// Set the default max rpc retry value if necessary
if (maxRpcRetries == 0)
maxRpcRetries = DEFAULT_MAX_RPC_RETRIES;
// Acquire our mutex
pthread_mutex_lock(&clientMutex);
try {
// tbd - add code to allow us to share endpoints to the same destination that are already opened
//
// Instantiate a RemoteEndPoint object and keep track of it
// with a smart pointer.
SmartRemoteEndPoint *pSmartRemoteEndPoint = new SmartRemoteEndPoint(new RemoteEndPoint(appMultithreaded,
maxRpcRetries,
port,
address));
// Allocate a handle for the endpoint
uint32_t handle = remoteEndPointHandleAllocator ++;
// Insert the new RemoteEndPoint into the REP map
REPIterBoolPair insertResult;
insertResult = repMap.insert(make_pair(handle, pSmartRemoteEndPoint));
if (!insertResult.second)
{
// Insertion failed
DbgTrace(0, "IpcClientOpenInetRemoteEndPoint- Unable to insert RemoteEndPoint into REP\n", 0);
delete pSmartRemoteEndPoint;
}
else
{
// RemoteEndPoint inserted in the REP map, success.
*pEndPointHandle = handle;
retStatus = 0;
}
} catch (...) {
DbgTrace(0, "IpcClientOpenInetRemoteEndPoint- Exception caught\n", 0);
}
pthread_mutex_unlock(&clientMutex);
}
else
{
DbgTrace(0, "IpcClientOpenInetRemoteEndPoint- Not initialized\n", 0);
}
exit:
DbgTrace(1, "IpcClientOpenInetRemoteEndPoint- End, status = %08X\n", retStatus);
return retStatus;
}
//++=======================================================================
extern "C"
int
IpcClientCloseRemoteEndPoint(
IN uint32_t endPointHandle)
//
// Arguments In: endpointHandle - Handle of the endpoint being closed.
//
//
// Arguments Out: None.
// the endpoint handle.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to close a remote endpoint.
//
// Note: The service should have been initialized before calling
// this procedure.
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "IpcClientCloseRemoteEndPoint- Start\n", 0);
// Verify that we have been initialized
if (svcInitialized)
{
// Acquire our mutex
pthread_mutex_lock(&clientMutex);
// Find the appropriate RemoteEndPoint object in the REP Map using
// the handle provided by the caller.
REPMapIter iter = repMap.find(endPointHandle);
if (iter != repMap.end())
{
// Object was found in the map, remove it.
SmartRemoteEndPoint *pSmartRemoteEndPoint = iter->second;
repMap.erase(iter);
// Release our mutex before deleting the endpoint
pthread_mutex_unlock(&clientMutex);
// Close the endpoint
delete pSmartRemoteEndPoint;
// Success
retStatus = 0;
}
else
{
DbgTrace(0, "IpcClientCloseRemoteEndPoint- Invalid handle\n", 0);
// Release our mutex
pthread_mutex_unlock(&clientMutex);
}
}
else
{
DbgTrace(0, "IpcClientCloseRemoteEndPoint- Not initialized\n", 0);
}
exit:
DbgTrace(1, "IpcClientCloseRemoteEndPoint- End, status = %08X\n", retStatus);
return retStatus;
}
//++=======================================================================
extern "C"
int
IpcClientSubmitReq(
IN uint32_t endPointHandle,
IN char *pClientData,
IN int clientDataLen,
INOUT char **ppServerData,
INOUT int *pServerDataLen)
//
// Arguments In: endPointHandle - Handle of the remote endpoint that will
// be the target of the request.
//
// pClientData - Pointer to client data that must be sent to
// the server. Buffer is NEVER released by the
// procedure.
//
// clientDataLen - Length of the client data.
//
// Arguments Out: ppServerData - Pointer to variable that will receive a
// pointer to the buffer containing the data
// received from the server.
//
// The returned buffer always contains a NULL after the
// data indicated. You may be able to leverage this to
// treat the data as a NULL terminated string in cases
// where the request consists of ASCII characters.
//
// pServerDataLen - Pointer to variable that will receive the
// length of the data received from the server.
//
// Returns: 0 == Request completed gracefully
// -1 == Request did not complete gracefully
//
// Abstract: Method to submit a request.
//
// Notes: The routine blocks until the request completes.
//
// The buffer returned with the server data must be released
// by the calling application by calling free().
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "IpcClientSubmitReq- Start\n", 0);
// Verify that we have been initialized
if (svcInitialized)
{
// Acquire our mutex
pthread_mutex_lock(&clientMutex);
// Find the appropriate RemoteEndPoint object in the REP Map using
// the handle provided by the caller.
REPMapIter iter = repMap.find(endPointHandle);
if (iter != repMap.end())
{
// Object was found in the map, use it to submit
// the request.
SmartRemoteEndPoint *pSmartRemoteEndPoint = new SmartRemoteEndPoint(*(iter->second));
// Release our mutex before deleting the endpoint
pthread_mutex_unlock(&clientMutex);
// Submit the request
retStatus = (*pSmartRemoteEndPoint)->submitReq(pClientData,
clientDataLen,
ppServerData,
pServerDataLen);
// Get rid of the reference to the remote endpoint
delete pSmartRemoteEndPoint;
}
else
{
DbgTrace(0, "IpcClientSubmitReq- Invalid handle\n", 0);
// Release our mutex
pthread_mutex_unlock(&clientMutex);
}
}
else
{
DbgTrace(0, "IpcClientSubmitReq- Not initialized\n", 0);
}
DbgTrace(1, "IpcClientSubmitReq- End, retStatus = %08X\n", retStatus);
return retStatus;
}
//++=======================================================================
extern "C"
int
IpcClientInit(
IN char *pName,
IN bool multithreaded,
IN int debugLevel,
IN bool useSyslog)
//
// Arguments In: pName - Pointer to string containing the name that the
// calling application wants associated with the
// debug logs emitted by the library.
//
// multithreaded - Set to TRUE if the process is
// multithreaded.
//
// debugLevel - The level that the library should use for
// determining what information should be logged
// for debugging purposes. 0 being the lowest
// level.
//
// useSyslog - Set to TRUE to log debug statements using Syslog,
// else debugs are log to stderr.
//
// Arguments Out: None.
//
// Returns: 0 == Success
// -1 == Failure
//
// Abstract: Method to initialize the IPC infrastructure for process.
//
// Note: It is necessary to call the appropriate function to
// set the server address before a request can be submitted.
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "IpcClientInit- Start\n", 0);
// Check input parameters
if (pAppName == NULL)
{
DbgTrace(0, "IpcClientInit- Invalid parameter\n", 0);
goto exit;
}
// Verify that we have not been initialized already
if (!svcInitialized)
{
// Save a copy of the application name
pAppName = new char[strlen(pName) + 1];
if (pAppName == NULL)
{
DbgTrace(0, "IpcClientInit- Memory allocation failure\n", 0);
goto exit;
}
strcpy(pAppName, pName);
// Save the app multithreaded information
appMultithreaded = multithreaded;
// Save the rest of the debug settings
DebugLevel = debugLevel;
UseSyslog = useSyslog;
// Initialize our mutexes
pthread_mutex_init(&clientMutex, NULL);
pthread_mutex_init(&interlockedMutex, NULL);
// Success
svcInitialized = true;
retStatus = 0;
}
else
{
DbgTrace(0, "IpcClientInit- Initialized already\n", 0);
}
exit:
DbgTrace(1, "IpcClientInit- End, status = %08X\n", retStatus);
return retStatus;
}
//++=======================================================================
extern "C"
void
IpcClientShutdown(void)
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Method to shutdown the IPC infrastructure for process.
//
// L2
//=======================================================================--
{
DbgTrace(1, "IpcClientShutdown- Start\n", 0);
// Verify that we have been initialized
if (svcInitialized)
{
// Forget about having been initialized
svcInitialized = false;
// Clean up the REP map
pthread_mutex_lock(&clientMutex);
while (!repMap.empty())
{
REPMapIter iter = repMap.begin();
SmartRemoteEndPoint *pSmartRemoteEndPoint = iter->second;
repMap.erase(iter);
pthread_mutex_unlock(&clientMutex);
delete pSmartRemoteEndPoint;
pthread_mutex_lock(&clientMutex);
}
pthread_mutex_unlock(&clientMutex);
// Free the AppName string if necessary
if (pAppName != unInitialized)
{
delete[] pAppName;
pAppName = unInitialized;
}
// Wait until all of the channels are gone
while (numCChannelObjects)
sleep(0); // Only suffer a time-slice
sleep(0);
}
else
{
DbgTrace(0, "IpcClientShutdown- Not initialized\n", 0);
}
DbgTrace(1, "IpcClientShutdown- End\n", 0);
}
//++=======================================================================
static void __attribute__((destructor))
so_fini()
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Library un-initialization routine.
//
// L2
//=======================================================================--
{
DbgTrace(0, "so_fini- Start\n", 0);
IpcClientShutdown();
}
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,332 @@
/***********************************************************************
*
* 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 "ipcint.h"
#include "cchannel.h"
#include "clientreq.h"
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//
// Object Counters
//
unsigned long numClientReqObjects = 0;
//++=======================================================================
ClientReq::ClientReq(
uint32_t reqId) :
m_reqId (reqId),
m_pServerData (NULL),
m_submitThreadActive (true),
m_completed (false),
m_internalProblem (false)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ClientReq::ClientReq- Start, Obj = %08X\n", this);
// Initialize the mutex
if (pthread_mutex_init(&m_mutex, NULL) != 0)
{
DbgTrace(0, "ClientReq::ClientReq- Mutex initialization failed\n", 0);
// Throw exception
throw bad_alloc();
}
// Initialize the condition
if (pthread_cond_init(&m_condition, NULL) != 0)
{
DbgTrace(0, "ClientReq::ClientReq- Condition initialization failed\n", 0);
// Destroy the allocated mutex
pthread_mutex_destroy(&m_mutex);
// Throw exception
throw bad_alloc();
}
// Increment the object count
InterlockedIncrement(&numClientReqObjects);
DbgTrace(1, "ClientReq::ClientReq- End\n", 0);
} /*-- ClientReq::ClientReq() --*/
//++=======================================================================
ClientReq::~ClientReq(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ClientReq::~ClientReq- Start, Obj = %08X\n", this);
// Cleanup resources allocated for the object
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_condition);
// Release any server data that we may have
if (m_pServerData != NULL)
free(m_pServerData);
// Decrement the object count
InterlockedDecrement(&numClientReqObjects);
DbgTrace(1, "ClientReq::~ClientReq- End\n", 0);
} /*-- ClientReq::~ClientReq() --*/
//++=======================================================================
void
ClientReq::processServerData(
char *pServerData,
int serverDataLength)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ClientReq::processServerData- Start, Obj = %08X\n", this);
// Acquire exclusive access to the object
pthread_mutex_lock(&m_mutex);
// Save server dataetup the ServerData object
m_pServerData = pServerData;
m_serverDataLen = serverDataLength;
// Mark the request as completed
m_completed = true;
// Check if we must awaken the thread that submitted the request
// so that it can service the server data.
if (!m_submitThreadActive)
{
// The submit thread is not active, awaken it.
m_submitThreadActive = true;
pthread_cond_signal(&m_condition);
}
// Release exclusive access to the object
pthread_mutex_unlock(&m_mutex);
DbgTrace(1, "ClientReq::processServerData- End\n", 0);
} /*-- ClientReq::processServerData() --*/
//++=======================================================================
void
ClientReq::processError(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ClientReq::processError- Start, Obj = %08X\n", this);
// Acquire exclusive access to the object
pthread_mutex_lock(&m_mutex);
// Record that we suffered an internal problem and mark the
// request as completed.
m_internalProblem = true;
m_completed = true;
// Check if we must awaken the thread that submitted the request
// so that it can deal with the problem.
if (!m_submitThreadActive)
{
// The submit thread is not active, awaken it.
m_submitThreadActive = true;
pthread_cond_signal(&m_condition);
}
// Release exclusive access to the object
pthread_mutex_unlock(&m_mutex);
DbgTrace(1, "ClientReq::processError- End\n", 0);
} /*-- ClientReq::processError() --*/
//++=======================================================================
int
ClientReq::waitForCompletion(
char **ppResponseData,
int *pResponseDataLength)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus;
int oldCancelState;
DbgTrace(1, "ClientReq::waitForCompletion- Start, Obj = %08X\n", this);
// Make sure that the thread can not be cancelled while executing
// in this routine.
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldCancelState);
// Acquire exclusive access to the object
pthread_mutex_lock(&m_mutex);
// Continue until the request completes
while (!m_completed)
{
// Wait to be awaken
//
// Indicate that we are no longer active
m_submitThreadActive = false;
pthread_cond_wait(&m_condition, &m_mutex);
}
// Release exclusive access to the object
pthread_mutex_unlock(&m_mutex);
// Determine the parameters that should be returned
if (!m_internalProblem)
{
retStatus = 0;
*ppResponseData = m_pServerData;
*pResponseDataLength = m_serverDataLen;
// Forget about the server data buffer
m_pServerData = NULL;
}
else
retStatus = -1;
DbgTrace(1, "ClientReq::waitForCompletion- End, retStatus = %08X\n", retStatus);
// Restore the threads cancel state
pthread_setcancelstate(oldCancelState, NULL);
return retStatus;
} /*-- ClientReq::waitForCompletion() --*/
//++=======================================================================
ClientReq::CompletionStatus
ClientReq::completionStatus(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
CompletionStatus compStatus;
DbgTrace(1, "ClientReq::completionStatus- Start, Obj = %08X\n", this);
// Check if we encountered any issues
if (m_internalProblem)
{
compStatus = ErrorCompletionStatus;
}
else
{
compStatus = SuccessCompletionStatus;
}
DbgTrace(1, "ClientReq::completionStatus- End, compStatus = %08X\n", compStatus);
return compStatus;
} /*-- ClientReq::completionStatus() --*/
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,173 @@
/***********************************************************************
*
* 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 _CLIENTREQ_
#define _CLIENTREQ_
//===[ Include files ]=====================================================
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//===[ Type definitions ]==================================================
//
// Client Request Class
//
class ClientReq
{
// Req Id
uint32_t m_reqId;
// Server Data
char *m_pServerData;
int m_serverDataLen;
// Flag indicating the state of the submitting
// thread.
bool m_submitThreadActive;
// Flag indicating that the Request has completed.
bool m_completed;
// Flag indicating that a problem was encountered
// while processing the Request.
bool m_internalProblem;
// Synchronization variables
pthread_mutex_t m_mutex;
pthread_cond_t m_condition;
public:
// Completion Statuses
enum CompletionStatus
{
SuccessCompletionStatus = 1,
ErrorCompletionStatus
};
//
// Constructor
//
// Parameters:
// reqId (input) -
// Id of the Request.
//
// clientHandler (input) -
// Pointer to Client Handler routine.
//
// Abstract: Constructs ClientReq object.
//
// Returns: Nothing.
//
ClientReq(uint32_t reqId);
//
// Destructor
~ClientReq(void);
//
// Process Server Data routine
//
// Parameters:
// pServerData (input) -
// Pointer to buffer containing the server data.
// Buffer is released by call to the routine.
//
// serverDataLength (input) -
// Length of the server data.
//
// Abstract: Processes server data.
//
// Returns: Nothing.
//
void processServerData(char *pServerData,
int serverDataLength);
//
// Process Error routine
//
// Parameters: None.
//
// Abstract: Processes channel and server error
// indication.
//
// Returns: Nothing.
//
void processError(void);
//
// Wait For Completion routine
//
// Parameters:
// ppResponseData (input/output) -
// Pointer to variable that will receive pointer to
// buffer containing the data sent by the server.
//
// pResponseDataLength (input/output) -
// Pointer to variable that will receive the length
// of the data sent by the server.
//
//
// Abstract: Waits for the Request completion.
//
// Returns: 0 == Request completed gracefully
// -1 == Request did not complete gracefully
//
int waitForCompletion(char **ppResponseData,
int *pResponseDataLength);
//
// Completion status
//
// Parameters: None.
//
// Abstract: Obtains the request completion status.
//
// Returns: Request completion status.
// status in order to find out.
//
ClientReq::CompletionStatus completionStatus(void);
};
//===[ Function prototypes ]===============================================
#endif // _CLIENTREQ_
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,441 @@
/***********************************************************************
*
* 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 "ipcint.h"
#include "cchannel.h"
#include "clientreq.h"
#include "remoteendpoint.h"
#include <assert.h> // Ensure that NDEBUG is defined for release builds!
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
#define REMOTE_ENDPOINT_SIGNATURE 0X50454D52 // RMEP
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//
// Object Counters
//
unsigned long numRemoteEndPointObjects = 0;
//++=======================================================================
RemoteEndPoint::RemoteEndPoint(
bool multithreaded,
int maxRpcRetries,
char *pSocketFileName) :
m_signature (REMOTE_ENDPOINT_SIGNATURE),
m_numChannelSubmits (0),
m_maxRpcRetries (maxRpcRetries)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "RemoteEndPoint::RemoteEndPoint- Start, Obj = %08X\n", this);
// Initialize our mutex
pthread_mutex_init(&m_mutex, NULL);
// Set the necessary information in the m_serverUnAddr variable
m_serverUnAddr.sun_family = AF_UNIX;
strcpy(m_serverUnAddr.sun_path, pSocketFileName);
// Set the necessary flags to indicate that DOMAIN sockets
// should be used for communications.
m_Use_PF_UNIX = true;
m_Use_AF_INET = false;
// Setup the number of channels that we may have based on
// whether the application is multi-threaded or not.
if (multithreaded)
m_numCChannels = MAX_CHANNELS_PER_ENDPOINT;
else
m_numCChannels = 1;
// Instantiate entries in SmartCChannel vector
try {
for (int i = 0; i < m_numCChannels; i++)
m_cchannelVector.push_back(SmartCChannelPointer());
} catch (...) {
DbgTrace(0, "RemoteEndPoint::RemoteEndPoint- Exception caught while initializing the cchannelVector\n", 0);
throw bad_alloc();
}
// Increment the object count
InterlockedIncrement(&numRemoteEndPointObjects);
DbgTrace(1, "RemoteEndPoint::RemoteEndPoint- End\n", 0);
} /*-- RemoteEndPoint::RemoteEndPoint() --*/
//++=======================================================================
RemoteEndPoint::RemoteEndPoint(
bool multithreaded,
int maxRpcRetries,
unsigned short int port,
uint32_t address) :
m_signature (REMOTE_ENDPOINT_SIGNATURE),
m_numChannelSubmits (0),
m_maxRpcRetries (maxRpcRetries)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "RemoteEndPoint::RemoteEndPoint- Start, Obj = %08X\n", this);
// Initialize our mutex
pthread_mutex_init(&m_mutex, NULL);
// Set the necessary information in the serverInAddr variable
m_serverInAddr.sin_family = AF_INET;
m_serverInAddr.sin_port = htons(port);
m_serverInAddr.sin_addr.s_addr = htonl(address);
// Set the necessary flags to indicate that TCP sockets
// should be used for communications.
m_Use_AF_INET = true;
m_Use_PF_UNIX = false;
// Setup the number of channels that we may have based on
// whether the application is multi-threaded or not.
if (multithreaded)
m_numCChannels = MAX_CHANNELS_PER_ENDPOINT;
else
m_numCChannels = 1;
// Instantiate entries in SmartCChannel vector
try {
for (int i = 0; i < m_numCChannels; i++)
m_cchannelVector.push_back(SmartCChannelPointer());
} catch (...) {
DbgTrace(0, "RemoteEndPoint::RemoteEndPoint- Exception caught while initializing the cchannelVector\n", 0);
throw bad_alloc();
}
// Increment the object count
InterlockedIncrement(&numRemoteEndPointObjects);
DbgTrace(1, "RemoteEndPoint::RemoteEndPoint- End\n", 0);
} /*-- RemoteEndPoint::RemoteEndPoint() --*/
//++=======================================================================
RemoteEndPoint::~RemoteEndPoint(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "RemoteEndPoint::~RemoteEndPoint- Start, Obj = %08X\n", this);
// Clean up all allocated SmartCChannel objects
for (int i = 0; i < m_cchannelVector.size(); i++)
{
if (m_cchannelVector[i].getPointer() != NULL)
{
CChannel *pCChannel = *(m_cchannelVector[i].getPointer());
pCChannel->closeChannel();
}
}
m_cchannelVector.clear();
// Decrement the object count
InterlockedDecrement(&numRemoteEndPointObjects);
DbgTrace(1, "RemoteEndPoint::~RemoteEndPoint- End\n", 0);
} /*-- RemoteEndPoint::~RemoteEndPoint() --*/
//++=======================================================================
SmartCChannel*
RemoteEndPoint::getCChannel(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
SmartCChannel *pSmartCChannel = NULL;
int channelSelector = (m_numChannelSubmits++) % m_numCChannels;
DbgTrace(1, "RemoteEndPoint::getCChannel- Start, Obj = %08X\n", this);
#if DEBUG
assert(m_signature == REMOTE_ENDPOINT_SIGNATURE);
#endif
// Obtain our mutex
pthread_mutex_lock(&m_mutex);
// Check if there is an available and usable channel for the client
if (m_cchannelVector[channelSelector].getPointer() != NULL
&& (*m_cchannelVector[channelSelector].getPointer())->ok())
{
// Use the available channel
pSmartCChannel = new SmartCChannel(*m_cchannelVector[channelSelector].getPointer());
}
else
{
// The channel is either unavailable or unusable, clean up
// the channel if it is indeed unusable.
if (m_cchannelVector[channelSelector].getPointer() != NULL)
{
// Clean up the channel
CChannel *pCChannel = *m_cchannelVector[channelSelector].getPointer();
pCChannel->closeChannel();
delete m_cchannelVector[channelSelector].getPointer();
m_cchannelVector[channelSelector].setPointer(NULL);
}
CChannel *pCChannel;
try {
// Use the appropriate server address when instantiating
// the CChannel object.
if (m_Use_PF_UNIX)
{
// PF_UNIX
pCChannel = new CChannel(&m_serverUnAddr);
}
else
{
// Assume AF_INET
pCChannel = new CChannel(&m_serverInAddr);
}
// CChannel object created, now associate a SmartCChannel
// object with it. It is important to do this to keep
// the object from being deleted as we initialize it.
m_cchannelVector[channelSelector].setPointer(new SmartCChannel(pCChannel));
// Initialize the CChannel
if (pCChannel->init() == 0)
{
// CChannel initialization succeeded, use it to
// satisfy the caller.
pSmartCChannel = new SmartCChannel(*m_cchannelVector[channelSelector].getPointer());
}
else
{
// CChannel initialization failed
delete m_cchannelVector[channelSelector].getPointer();
m_cchannelVector[channelSelector].setPointer(NULL);
}
}
catch (...) {
DbgTrace(0, "getCChannel- Exception caught\n", 0);
// Try to clean things up just in case
if (m_cchannelVector[channelSelector].getPointer())
{
delete m_cchannelVector[channelSelector].getPointer();
m_cchannelVector[channelSelector].setPointer(NULL);
}
else
{
if (pCChannel != NULL)
delete pCChannel;
}
}
}
// Release client mutex
pthread_mutex_unlock(&m_mutex);
DbgTrace(1, "RemoteEndPoint::getCChannel- End\n", 0);
return pSmartCChannel;
} /*-- RemoteEndPoint::getCChannel() --*/
//++=======================================================================
int
RemoteEndPoint::submitReq(
char *pClientData,
int clientDataLen,
char **ppServerData,
int *pServerDataLen)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "RemoteEndPoint::submitReq- Start, Obj = %08X\n", this);
try {
SmartCChannel *pSmartCChannel;
// Perform the following in a loop to deal with abnormal connection terminations
unsigned long rpcRetryCount = 0;
bool okToRetry = true;
while (rpcRetryCount < m_maxRpcRetries)
{
// Get SmartCChannel
pSmartCChannel = getCChannel();
if (pSmartCChannel != NULL)
{
// Get pointer to channel object
CChannel *pCChannel = *pSmartCChannel;
// Allocate a requestId
uint32_t reqId = pCChannel->allocReqId();
// Allocate client request object.
ClientReq clientReq(reqId);
// Submit the request via the channel
if (pCChannel->submitReq(reqId,
clientReq,
pClientData,
clientDataLen) == 0)
{
// Request submission over the channel succeeded, now
// wait for the completion of the request.
if (clientReq.waitForCompletion(ppServerData,
pServerDataLen) == 0)
{
// Now proceed based on the completion status
ClientReq::CompletionStatus compStatus = clientReq.completionStatus();
if (compStatus == ClientReq::SuccessCompletionStatus)
{
// Success
retStatus = 0;
}
else
{
// Received a failure from the server, do not retry.
okToRetry = false;
}
}
else
{
// Error waiting for the completion.
okToRetry = false;
}
// Remove the request from the channel
pCChannel->removeReq(reqId);
}
else
{
DbgTrace(0, "RemoteEndPoint::submitReq- Request submittion over the channel failed\n", 0);
// Remove the request from the channel
pCChannel->removeReq(reqId);
}
// Delete the SmartCChannel
delete pSmartCChannel;
}
else
{
DbgTrace(0, "RemoteEndPoint::submitReq- Channel unavailable\n", 0);
}
// Stop trying if the RPC succeeded or if it is not ok to retry
if (retStatus == 0
|| !okToRetry)
break;
// Account for this RPC try
rpcRetryCount ++;
DbgTrace(0, "RemoteEndPoint::submitReq- Will attempt to retry RPC, count = %d\n", rpcRetryCount);
}
}
catch(...) {
DbgTrace(0, "RemoteEndPoint::submitReq- Exception caught\n", 0);
}
DbgTrace(1, "RemoteEndPoint::submitReq- End\n", 0);
return retStatus;
} /*-- RemoteEndPoint::submitReq() --*/
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,203 @@
/***********************************************************************
*
* 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 _REMOTEENDPOINT_
#define _REMOTEENDPOINT_
//===[ Include files ]=====================================================
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
#define MAX_CHANNELS_PER_ENDPOINT 3
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//===[ Type definitions ]==================================================
//
// Server Thread Class
//
class RemoteEndPoint : public ObjRef
{
//
// Class for maintaining SmartCChannel pointers within the daemonVector.
//
class SmartCChannelPointer
{
private:
SmartCChannel *m_pSmartCChannel;
public:
SmartCChannelPointer() : m_pSmartCChannel(NULL) {}
~SmartCChannelPointer() { if (m_pSmartCChannel != NULL) delete m_pSmartCChannel; }
SmartCChannel* getPointer() { return m_pSmartCChannel; }
void setPointer(SmartCChannel *pSmartCChannel) { m_pSmartCChannel = pSmartCChannel; }
};
// Signature
unsigned long m_signature;
// End-point address
bool m_Use_AF_INET;
bool m_Use_PF_UNIX;
struct sockaddr_in m_serverInAddr;
struct sockaddr_un m_serverUnAddr;
// SmartCChannelPointers vector
vector<SmartCChannelPointer> m_cchannelVector;
int m_numCChannels;
// Endpoint mutex
pthread_mutex_t m_mutex;
// Number of submits made to the endpoint
int m_numChannelSubmits;
// Max number of Rpc retries
int m_maxRpcRetries;
public:
//
// Destructor
~RemoteEndPoint(void);
//
// Constructor
//
// Parameters:
// multithreaded (input) -
// Set to TRUE if the process is
// multithreaded.
//
// maxRpcRetries (input) -
// Max Rpc retries.
//
// pSocketFileName (input) -
// Pointer to string containing the name
// of the socket file.
//
// Abstract: Constructs RemoteEndPoint object and initializes it using
// a domain socket file name.
//
// Returns: Nothing.
//
RemoteEndPoint(bool multiThreaded,
int maxRpcRetries,
char *pSocketFileName);
//
// Constructor
//
// Parameters:
// multithreaded (input) -
// Set to TRUE if the process is
// multithreaded.
//
// maxRpcRetries (input) -
// Max Rpc retries.
//
// port (input) -
// Server's listening port number.
//
// address (input) -
// The server's IP Address. Use
// 0x7F000001 if the endpoint is local.
//
// Abstract: Constructs RemoteEndPoint object and initializes it using
// a tcp socket address.
//
// Returns: Nothing.
//
RemoteEndPoint(bool multiThreaded,
int maxRpcRetries,
unsigned short int port,
uint32_t address);
//
// Get a SmartCChannel.
//
// Parameters: None.
//
// Abstract: Gets a SmartCChannel for submitting requests to the
// remote endpoint.
//
// Returns: Pointer to SmartCChannel object if successful, otherwise
// NULL.
//
SmartCChannel *getCChannel(void);
//
// Submit a request to the endpoint,
//
// Parameters:
// pClientData (input) -
// Pointer to client data that must be sent to
// the server. Buffer is NEVER released by the
// procedure.
//
// clientDataLen (input) -
// Length of the client data.
//
// ppServerData (input/output) -
// Pointer to variable that will receive a
// pointer to the buffer containing the data
// received from the server.
//
// pServerDataLen (input/output) -
// Pointer to variable that will receive the
// length of the data received from the server.
//
// Abstract: Method to submit a request.
//
// Returns: 0 == Request completed gracefully
// -1 == Request did not complete gracefully
//
// Note: The routine blocks until the request completes.
//
int submitReq(char *pClientData,
int clientDataLen,
char **ppServerData,
int *pServerDataLen);
};
typedef SmartPtr<RemoteEndPoint> SmartRemoteEndPoint;
//===[ Function prototypes ]===============================================
#endif // _REMOTEENDPOINT_
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,3 @@
#!/bin/bash
gcc -o TestClient testClient.c -g -I../../../../../include -L../../../../../lib/Release -lpthread -lcasa_c_ipc -Xlinker -rpath -Xlinker ../../../../../lib/Release

View File

@ -0,0 +1,301 @@
/***********************************************************************
*
* 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 <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <pthread.h>
#include <unistd.h>
#include <stdint.h>
#include "casa_s_ipc.h"
//===[ Type definitions ]==================================================
//
// DbgTrace macro define
//
#define DbgTrace(LEVEL, X, Y) { \
if (LEVEL == 0) \
printf(X, Y); \
else if (DebugLevel >= LEVEL) \
printf(X, Y); \
}
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
// Usage string
char usage[] = "\nTest: usage: [-c requestCount] [-t submitThreadCount] [-D DebugLevel]\n";
int DebugLevel = 3;
// Request count
int submitReqCount = 100;
// Submit thread count
int submitThreadCount = 1;
// Synch mutex
pthread_mutex_t testMutex;
bool errorDetected = false;
//++=======================================================================
void* SubmitThread(
uint32_t remoteEndPointHandle)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
char reqData[] = "This is the request data";
char *pReplyData;
int replyDataLen;
DbgTrace(1, "SubmitThread- Start\n", 0);
pthread_mutex_lock(&testMutex);
while (submitReqCount != 0
&& !errorDetected)
{
submitReqCount --;
pthread_mutex_unlock(&testMutex);
// Submit request to the server
if (IpcClientSubmitReq(remoteEndPointHandle,
reqData,
strlen(reqData),
&pReplyData,
&replyDataLen) != 0)
{
DbgTrace(0, "SubmitThread- Req submit error\n", 0);
errorDetected = true;
}
else
{
// Free the reply data buffer
free(pReplyData);
}
pthread_mutex_lock(&testMutex);
}
DbgTrace(1, "SubmitThread- End\n", 0);
// Exit
pthread_exit(NULL);
return 0; // never-reached!
}
//++=======================================================================
void
ExecuteTests(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
pthread_t thread;
int threadCreateStatus;
int threadCreatedCount = 0;
int i;
uint32_t endPointHandle;
DbgTrace(1, "ExecuteTests- Start\n", 0);
// Initialize the Client Ipc Subsystem
if (IpcClientInit("TestClient",
true,
DebugLevel,
false) == 0)
{
// Set the server listen address
if (IpcClientOpenInetRemoteEndPoint(5000,
0x7F000001,
0,
&endPointHandle) == 0)
{
// Start the configured number of threads to submit requests to
// the server.
for (i = 0; i < submitThreadCount; i++)
{
threadCreateStatus = pthread_create(&thread,
NULL,
(void*(*)(void*))SubmitThread,
(void*)endPointHandle);
if (threadCreateStatus == 0)
threadCreatedCount ++;
else
{
DbgTrace(0, "ExecuteTests- Error creating submit thread, error = %08X\n", threadCreateStatus);
}
}
// Wait for the requests to be submitted
if (threadCreatedCount != 0)
{
while (submitReqCount
&& !errorDetected)
sleep(1);
sleep(1);
}
// Close the remote endpoint
if (IpcClientCloseRemoteEndPoint(endPointHandle) != 0)
{
DbgTrace(0, "ExecuteTests- Error closing remote endpoint\n", 0);
}
}
else
{
DbgTrace(0, "ExecuteTests- Error opening remote endpoint\n", 0);
}
IpcClientShutdown();
sleep(1);
}
else
{
DbgTrace(0, "ExecuteTests- Ipc subsystem initialization failed\n", 0);
}
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;
int initialCount;
printf("**** Ipc Client test ****\n");
// Scan through the options specified
while (!doneScanning)
{
opterr = 0;
option = getopt(argc, argv, "c:t: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 'c':
// Set the submit request count
submitReqCount = atoi(optarg);
optionsSpecified++;
break;
case 't':
// Set the submit thread count
submitThreadCount = atoi(optarg);
optionsSpecified++;
break;
case '?':
// Invalid option detected
doneScanning = true;
invalidOption = true;
break;
default:
// Done scanning
doneScanning = true;
break;
}
}
// Do some sanity checking
if (!invalidOption)
{
printf("submitReqCount = %d\n", submitReqCount);
printf("submitThreadCount = %d\n", submitThreadCount);
initialCount = submitReqCount;
ExecuteTests();
printf("Submits issued = %d\n", initialCount - submitReqCount);
}
else
{
// Invalid option detected
printf(usage, argv[0]);
}
return 0;
} /*-- main() --*/

View File

@ -0,0 +1,39 @@
#######################################################################
#
# 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 =
DIST_SUBDIRS =
CFILES =
CPPFILES = channelproto.cpp
EXTRA_DIST = $(CFILES) $(CPPFILES) *.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

View File

@ -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>
*
***********************************************************************/
//===[ Include files ]=====================================================
#include "ipcint.h"
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
// Channel Packet Types
string DataCarrierTypeTemplate = "TypeXX";
string ReqDataCarrierType = "Type01";
string ReqErrorCarrierType = "Type02";
// Channel Packet Headers
string ReqIdHdr = "ReqIdHdr =";
string PayloadLengthHdr = "PayloadLength =";
// Req Data Pkt Hdr Template
string ReqDataPktHdrTemplate = "Type01\r\nReqIdHdr =XXXXXXXX\r\nPayloadLength =XXXXXXXX\r\n\r\n";
// Req Error Pkt Hdr Template
string ReqErrorPktHdrTemplate = "Type02\r\nReqIdHdr =XXXXXXXX\r\nPayloadLength =XXXXXXXX\r\n\r\n";
//++=======================================================================
int
ChannelProto::buildReqDataPktHdr(
uint32_t reqId,
int32_t payloadLength,
char *pPktHdr)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "ChannelProto::buildReqDataPktHdr- Start\n", 0);
try {
// - Req Data Packet Header Format -
//
// ReqDataCarrierType
// ReqIdHdr value (value format=%08X)
// PayloadLengthHdr value (value format=%08X)
//
// Setup the necessary value strings
char wrkBuffer[10];
sprintf(wrkBuffer, "%08X", reqId);
string reqIdValue = wrkBuffer;
sprintf(wrkBuffer, "%08X", payloadLength);
string payloadLengthValue = wrkBuffer;
// Format the header.
char* pCurr = pPktHdr;
memcpy(pCurr, ReqDataCarrierType.c_str(), ReqDataCarrierType.length());
pCurr += ReqDataCarrierType.length();
memcpy(pCurr, "\r\n", 2);
pCurr += 2;
memcpy(pCurr, ReqIdHdr.c_str(), ReqIdHdr.length());
pCurr += ReqIdHdr.length();
memcpy(pCurr, reqIdValue.c_str(), reqIdValue.length());
pCurr += reqIdValue.length();
memcpy(pCurr, "\r\n", 2);
pCurr += 2;
memcpy(pCurr, PayloadLengthHdr.c_str(), PayloadLengthHdr.length());
pCurr += PayloadLengthHdr.length();
memcpy(pCurr, payloadLengthValue.c_str(), payloadLengthValue.length());
pCurr += payloadLengthValue.length();
memcpy(pCurr, "\r\n\r\n", 4);
// Success
retStatus = 0;
}
catch (...) {
DbgTrace(0, "ChannelProto::buildReqDataPktHdr- Exception caught while creating header\n", 0);
}
DbgTrace(1, "ChannelProto::buildReqDataPktHdr- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- ChannelProto::buildReqDataPktHdr() --*/
//++=======================================================================
int
ChannelProto::buildReqErrorPktHdr(
uint32_t reqId,
int32_t payloadLength,
char *pPktHdr)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus = -1;
DbgTrace(1, "ChannelProto::buildReqErrorPktHdr- Start\n", 0);
try {
// - Req Error Packet Header Format -
//
// ReqErrorCarrierType
// ReqIdHdr value (value format=%08X)
// PayloadLengthHdr value (value format=%08X)
//
// Setup the necessary value strings
char wrkBuffer[10];
sprintf(wrkBuffer, "%08X", reqId);
string reqIdValue = wrkBuffer;
sprintf(wrkBuffer, "%08X", payloadLength);
string payloadLengthValue = wrkBuffer;
// Format the header.
char* pCurr = pPktHdr;
memcpy(pCurr, ReqErrorCarrierType.c_str(), ReqErrorCarrierType.length());
pCurr += ReqErrorCarrierType.length();
memcpy(pCurr, "\r\n", 2);
pCurr += 2;
memcpy(pCurr, ReqIdHdr.c_str(), ReqIdHdr.length());
pCurr += ReqIdHdr.length();
memcpy(pCurr, reqIdValue.c_str(), reqIdValue.length());
pCurr += reqIdValue.length();
memcpy(pCurr, "\r\n", 2);
pCurr += 2;
memcpy(pCurr, PayloadLengthHdr.c_str(), PayloadLengthHdr.length());
pCurr += PayloadLengthHdr.length();
memcpy(pCurr, payloadLengthValue.c_str(), payloadLengthValue.length());
pCurr += payloadLengthValue.length();
memcpy(pCurr, "\r\n\r\n", 4);
// Success
retStatus = 0;
}
catch (...) {
DbgTrace(0, "ChannelProto::buildReqErrorPktHdr- Exception caught while creating header\n", 0);
}
DbgTrace(1, "ChannelProto::buildReqErrorPktHdr- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- ChannelProto::buildReqErrorPktHdr() --*/
//++=======================================================================
ChannelProto::PacketTypes
ChannelProto::getPktType(
char &buff)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
PacketTypes packetType = UnknownPacketType;
DbgTrace(1, "ChannelProto::getPktType- Start\n", 0);
// Find the end of the Channel Packet Type
char *pCurr = &buff;
while (*pCurr != '\r')
pCurr ++;
// Found the end of the Channel Packet Type, now
// calculate its length.
int channelPktTypeLength = pCurr - &buff;
// Now start comparing
if (channelPktTypeLength == ReqDataCarrierType.length()
&& !memcmp(&buff, ReqDataCarrierType.c_str(), channelPktTypeLength))
{
// The type is Channel Req Data Carrier
packetType = ReqDataCarrierPacketType;
}
else if (channelPktTypeLength == ReqErrorCarrierType.length()
&& !memcmp(&buff, ReqErrorCarrierType.c_str(), channelPktTypeLength))
{
// The type is Channel Req Error Carrier
packetType = ReqErrorCarrierPacketType;
}
else
{
DbgTrace(0, "ChannelProto::getPktType- No match found\n", 0);
}
DbgTrace(1, "ChannelProto::getPktType- End, type = %d\n", packetType);
return packetType;
} /*-- ChannelProto::getPktType() --*/
//++=======================================================================
bool
ChannelProto::getReqIdAndPayloadLength(
char *pBuff,
int hdrLength,
uint32_t *pReqId,
int32_t *pPayloadLength)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
bool reqIdObtained = false;
bool payloadLengthObtained = false;
DbgTrace(1, "ChannelProto::getReqIdAndPayloadLength- Start\n", 0);
char *pCurr = pBuff;
char *pChannelHdr = NULL;
int bytesLeft = hdrLength;
// Skip the Channel Packet Type
while (bytesLeft >= 2)
{
if (*pCurr == '\r'
&& *(pCurr+1) == '\n')
{
// Found the end of the channel packet type
pCurr += 2;
bytesLeft -= 2;
break;
}
else
{
pCurr ++;
bytesLeft --;
}
}
// Start processing Channel Packet Headers
pChannelHdr = pCurr;
while (bytesLeft >= 2
&& (!reqIdObtained || !payloadLengthObtained))
{
if (*pCurr == '\r'
&& *(pCurr+1) == '\n')
{
// Found the end of the current channel header
pCurr += 2;
bytesLeft -= 2;
// Check if the line is empty or if it contained a
// channel header.
if ((pCurr - pChannelHdr) == 2)
{
// This was an empty line, which means that
// we reached the end of the channel packet header.
break;
}
else
{
// Check if the header is the Req Id Hdr
if (!reqIdObtained && (pCurr - pChannelHdr) > ReqIdHdr.length()
&& !memcmp(pChannelHdr, ReqIdHdr.c_str(), ReqIdHdr.length()))
{
// We found the Req Id Hdr, get the value.
char *pValue = pChannelHdr + ReqIdHdr.length();
// Temporarily NULL terminate the value
*(pCurr-2) = '\0';
// Convert the value to hex
*pReqId = strtoul(pValue, NULL, 16);
// Undo the damage that we did
*(pCurr-2) = '\r';
// Remember that the Req Id was obtained
reqIdObtained = true;
}
// Check if the header is the Payload Length Hdr
else if ((pCurr - pChannelHdr) > PayloadLengthHdr.length()
&& !memcmp(pChannelHdr, PayloadLengthHdr.c_str(), PayloadLengthHdr.length()))
{
// We found the Payload Length Hdr, get the value.
char *pValue = pChannelHdr + PayloadLengthHdr.length();
// Temporarily NULL terminate the value
*(pCurr-2) = '\0';
// Convert the value to hex
*pPayloadLength = strtoul(pValue, NULL, 16);
// Undo the damage that we did
*(pCurr-2) = '\r';
// Remember that the Payload Lenght was obtained
payloadLengthObtained = true;
}
// Get set to process the next header
pChannelHdr = pCurr;
}
}
else
{
pCurr ++;
bytesLeft --;
}
}
DbgTrace(1,
"ChannelProto::getReqIdAndPayloadLength- End, retStatus = %08X\n",
reqIdObtained && payloadLengthObtained);
return reqIdObtained && payloadLengthObtained;
} /*-- ChannelProto::getReqIdAndPayloadLength() --*/
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,157 @@
/***********************************************************************
*
* 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 _CHANNELPROTO_
#define _CHANNELPROTO_
//===[ Include files ]=====================================================
//===[ External data ]=====================================================
extern string ReqDataPktHdrTemplate;
extern string ReqErrorPktHdrTemplate;
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//===[ Type definitions ]==================================================
//
// ChannelProto Class Definition
//
class ChannelProto
{
public:
// Packet Types
enum PacketTypes
{
ReqDataCarrierPacketType = 1,
ReqErrorCarrierPacketType,
UnknownPacketType
};
//
// Build Req Data Packet Header routine
//
// Parameters:
// reqId (input) -
// Req id.
//
// payloadLength (input) -
// Length of the payload being carried by the packet.
//
// pPktHdt (input/output) -
// Pointer to buffer that will receive the header.
// Note, this buffer needs to be big eneough to
// contain the ReqDataPktHdrTemplate string.
//
// Abstract: Returns Req Data Pkt Hdr for the specified
// parameters.
//
// Returns: 0 if successful.
//
static int buildReqDataPktHdr(uint32_t reqId,
int32_t payloadLength,
char *pPktHdr);
//
// Build Req Error Packet Header routine
//
// Parameters:
// reqId (input) -
// Req id.
//
// payloadLength (input) -
// Length of the payload being carried by the packet.
//
// pPktHdt (input/output) -
// Pointer to buffer that will receive the header.
// Note, this buffer needs to be big eneough to
// contain the ReqErrorPktHdrTemplate string.
//
// Abstract: Returns Req Error Pkt Hdr for the specified
// parameters.
//
// Returns: 0 if successful.
//
static int buildReqErrorPktHdr(uint32_t reqId,
int32_t payloadLength,
char *pPktHdr);
//
// Get Channel Packet Type routine
//
// Parameters:
// buff (input) -
// Reference to buffer containing the packet data.
//
// Abstract: Returns the type of the specified channel packet.
//
// Returns: Channel packet type.
//
static PacketTypes getPktType(char &buff);
//
// Get Req Id and Payload Length Values routine
//
// Parameters:
// buff (input) -
// Reference to buffer containing the packet data.
//
// hdrLength (input) -
// Length of the channel header.
//
// pReqId (input/output) -
// Pointer to variable that will receive the req id.
//
// pPayloadLength (input/output) -
// Pointer to variable that will receive the payload length.
//
// Abstract: Returns the values of the ReqId and PayloadLength headers
// present in the channel packet header.
//
// Returns: True if successful.
//
static bool getReqIdAndPayloadLength(char *pBuff,
int hdrLength,
uint32_t *pReqId,
int32_t *pPayloadLength);
};
//===[ Function prototypes ]===============================================
#endif // _CHANNELPROTO_
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,152 @@
/**********************\*************************************************
*
* 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 _IPCINT_
#define _IPCINT_
//===[ Include files ]=====================================================
#include <iostream>
#include <string>
#include <list>
#include <map>
#include <vector>
using namespace std;
extern "C" {
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <syslog.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <assert.h> // Ensure that NDEBUG is defined for release builds!
#include <sys/ipc.h>
}
//===[ External data ]=====================================================
extern int DebugLevel;
extern bool UseSyslog;
extern char *pAppName;
extern pthread_mutex_t interlockedMutex;
//===[ Macro definitions ]=================================================
//
// DbgTrace macro define
//
#define MAX_FORMAT_STRING_LEN 1024
#define DbgTrace(LEVEL, X, Y) { \
if (LEVEL == 0 || DebugLevel >= LEVEL) { \
if (UseSyslog) \
syslog(LOG_USER | LOG_INFO, X, Y); \
else { \
char *pFormatString = new char[MAX_FORMAT_STRING_LEN]; \
if (pFormatString) { \
snprintf(pFormatString, MAX_FORMAT_STRING_LEN, X, Y); \
fprintf(stderr, "%s -%s", pAppName, pFormatString); \
delete[] pFormatString; \
} \
} \
} \
}
//
// Interlocked Increment and Decrement macros
//
// Well, kind of interlocked :-).
//
__inline static unsigned long
InterlockedIncrement(unsigned long *pValue)
{
unsigned long retVal;
pthread_mutex_lock(&interlockedMutex);
(*pValue) ++;
retVal = *pValue;
pthread_mutex_unlock(&interlockedMutex);
return retVal;
}
__inline static unsigned long
InterlockedDecrement(unsigned long *pValue)
{
unsigned long retVal;
pthread_mutex_lock(&interlockedMutex);
(*pValue) --;
retVal = *pValue;
pthread_mutex_unlock(&interlockedMutex);
return retVal;
}
__inline static uint32_t
InterlockedIncrement(uint32_t *pValue)
{
uint32_t retVal;
pthread_mutex_lock(&interlockedMutex);
(*pValue) ++;
retVal = *pValue;
pthread_mutex_unlock(&interlockedMutex);
return retVal;
}
__inline static uint32_t
InterlockedDecrement(uint32_t *pValue)
{
uint32_t retVal;
pthread_mutex_lock(&interlockedMutex);
(*pValue) --;
retVal = *pValue;
pthread_mutex_unlock(&interlockedMutex);
return retVal;
}
//===[ Include files ]=====================================================
#include "smartptr.h"
#include "channelproto.h"
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
#endif // _IPCINT_
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,275 @@
/***********************************************************************
*
* 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.
*
***********************************************************************/
#ifndef SMARTPTR_H
#define SMARTPTR_H
/*******************************************************************************
* Include Files
*******************************************************************************/
/*******************************************************************************
* Definitions
*******************************************************************************/
/*******************************************************************************
* Types and Classes
*******************************************************************************/
//------------------------------------------------------------------------------
// Reference Object
//
// In order to use the SmartPtr<> class, the object type used to instantiate
// the SmartPtr template must inheirit from the ObjRef class.
//
//------------------------------------------------------------------------------
class ObjRef
{
//---------------------------------------------------------------------------
// Public interface
//
public:
ObjRef() : m_Count(0) {}
void IncRefCount(void)
{
InterlockedIncrement(&m_Count);
}
bool DecRefCount(void)
{
if ((m_Count > 0) && (InterlockedDecrement(&m_Count) == 0))
{
return true;
}
else
{
return false;
}
}
unsigned int GetRefCount(void) const
{
return m_Count;
}
//---------------------------------------------------------------------------
// Private data
//
private:
mutable unsigned long m_Count;
};
//------------------------------------------------------------------------------
// SmartPtr Object
//
//------------------------------------------------------------------------------
template<class T>
class SmartPtr
{
//---------------------------------------------------------------------------
// Public interface
//
public:
SmartPtr();
SmartPtr(T* ptr);
SmartPtr(const SmartPtr<T>& ref);
virtual ~SmartPtr();
operator bool (void) const;
bool operator! (void) const;
bool operator== (SmartPtr<T>& ref) const;
bool operator!= (SmartPtr<T>& ref) const;
SmartPtr<T>& operator= (const SmartPtr<T>& ref);
SmartPtr<T>& operator= (T* ptr);
T& operator* (void) const;
T* operator-> (void) const;
operator T* (void) const;
//---------------------------------------------------------------------------
// Private interface
//
private:
void deleteObject(void);
void resetPtr(T* newPtr);
//---------------------------------------------------------------------------
// Private data
//
private:
T* m_Ptr;
};
template<class T>
inline SmartPtr<T>::SmartPtr() :
m_Ptr(0)
{
} // End of SmartPtr::SmartPtr()
template<class T>
inline SmartPtr<T>::SmartPtr(T* ptr) :
m_Ptr(0)
{
resetPtr(ptr);
} // End of SmartPtr::SmartPtr()
template<class T>
inline SmartPtr<T>::SmartPtr(const SmartPtr<T>& ref) :
m_Ptr(0)
{
resetPtr(ref.m_Ptr);
} // End of SmartPtr::SmartPtr()
template<class T>
inline SmartPtr<T>::~SmartPtr()
{
deleteObject();
} // End of SmartPtr::~SmartPtr()
template<class T>
inline SmartPtr<T>::operator bool (void) const
{
return m_Ptr != 0;
} // End of SmartPtr::operator bool()
template<class T>
inline bool SmartPtr<T>::operator! (void) const
{
return m_Ptr == 0;
} // End of SmartPtr::operator!()
template<class T>
inline bool SmartPtr<T>::operator== (SmartPtr<T>& ref) const
{
return m_Ptr == ref.m_Ptr;
} // End of SmartPtr::operator==()
template<class T>
inline bool SmartPtr<T>::operator!= (SmartPtr<T>& ref) const
{
return m_Ptr != ref.m_Ptr;
} // End of SmartPtr::operator==()
template<class T>
inline SmartPtr<T>& SmartPtr<T>::operator= (const SmartPtr<T>& ref)
{
resetPtr(ref.m_Ptr);
return *this;
} // End of SmartPtr::operator=()
template<class T>
inline SmartPtr<T>& SmartPtr<T>::operator= (T* ptr)
{
resetPtr(ptr);
return *this;
} // End of SmartPtr::operator=()
template<class T>
inline T& SmartPtr<T>::operator* (void) const
{
return *m_Ptr;
} // End of SmartPtr::operator*()
template<class T>
inline T* SmartPtr<T>::operator-> (void) const
{
return m_Ptr;
} // End of SmartPtr::operator->()
template<class T>
inline SmartPtr<T>::operator T* (void) const
{
return m_Ptr;
} // End of SmartPtr::operator T*()
template<class T>
inline void SmartPtr<T>::deleteObject(void)
{
if (m_Ptr && m_Ptr->DecRefCount())
{
delete m_Ptr;
m_Ptr = 0;
}
} // End of SmartPtr::deleteObject()
template<class T>
inline void SmartPtr<T>::resetPtr(T* newPtr)
{
if (m_Ptr != newPtr)
{
deleteObject();
m_Ptr = newPtr;
if (m_Ptr)
{
// New object reference.
m_Ptr->IncRefCount();
}
}
} // End of SmartPtr::resetPtr()
#endif // SMARTPTR_H
/******************************************************************************/
/******************************************************************************/

View File

@ -0,0 +1,126 @@
#######################################################################
#
# 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
DEFINES = -DDBG
else
TARGET_CFG = Release
DEFINES = -DNDEBUG
endif
# Override the link setting for C++
LINK = g++
SUBDIRS =
DIST_SUBDIRS =
ROOT = ../../../..
LIBDIR = $(ROOT)/$(LIB)
# handle Mono secondary dependencies
export MONO_PATH := $(MONO_PATH)
COMMON = ../common
SERVER = .
MODULE_NAME = libcasa_s_ipc
MODULE_EXT = so
CFILES =
CPPFILES = schannel.cpp \
serverreq.cpp \
serverthread.cpp \
server.cpp
COMMONCPPFILES = channelproto.cpp
CSFILES_CSC :=
INCLUDES = -I. -I.. -I../common -I../../../../include
RESOURCES =
if LIB64
DEFINES += -D_LIB64
endif
CFLAGS += -Wno-format-extra-args -fno-strict-aliasing -fshort-wchar $(INCLUDES) $(DEFINES)
CPPFLAGS += -Wno-format-extra-args -fno-strict-aliasing -fshort-wchar -fPIC $(INCLUDES) $(DEFINES) $(RPM_OPT_FLAGS)
LIBS = -lpthread
LDFLAGS = -Bsymbolic -shared -Wl,-soname=$(MODULE_NAME).$(MODULE_EXT)
OBJDIR = ./$(TARGET_CFG)/$(LIB)
OBJS = $(addprefix $(OBJDIR)/, $(CFILES:%.c=%.o)) $(addprefix $(OBJDIR)/, $(COMMONCPPFILES:%.cpp=%.o)) $(addprefix $(OBJDIR)/, $(CPPFILES:%.cpp=%.o))
EXTRA_DIST = $(CFILES) $(CPPFILES) *.h
CUR_DIR := $(shell pwd)
all: $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT)
#
# Pattern based rules.
#
vpath %.c $(SERVER) $(COMMON)
vpath %.cpp $(SERVER) $(COMMON)
$(OBJDIR)/%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
$(OBJDIR)/%.o: %.cpp
$(CC) -c $(CPPFLAGS) -o $@ $<
$(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT): $(OBJDIR) $(OBJS)
@echo [======== Linking $@ ========]
$(LINK) -o $@ $(LDFLAGS) $(OBJS) $(LIBS)
cp -f $(OBJDIR)/$(MODULE_NAME).$(MODULE_EXT) $(LIBDIR)/$(TARGET_CFG)/$(MODULE_NAME).$(MODULE_EXT)
$(OBJDIR):
[ -d $(OBJDIR) ] || mkdir -p $(OBJDIR)
[ -d $(LIBDIR) ] || mkdir -p $(LIBDIR)
[ -d $(LIBDIR)/$(TARGET_CFG) ] || mkdir -p $(LIBDIR)/$(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

View File

@ -0,0 +1,776 @@
/***********************************************************************
*
* 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 "ipcint.h"
#include "schannel.h"
#include "serverreq.h"
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
extern int
ServiceRequest(
ServerReq *pServerReq);
extern void
RemoveFromSChannelList(
SChannel *pSChannel);
//===[ Manifest constants ]================================================
//
// Socket Mapping definitions
//
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define LINGER struct linger
#define SOCKADDR_IN struct sockaddr_in
#define closesocket close
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//
// Object Counters
//
unsigned long numSChannelObjects = 0;
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//++=======================================================================
SChannel::SChannel(
int connSocket) :
m_state (State_Connected),
m_socket (connSocket)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "SChannel::SChannel- Start, Obj = %08X\n", this);
// Initialize the mutex
if (pthread_mutex_init(&m_mutex, NULL) != 0)
{
DbgTrace(0, "SChannel::SChannel- Mutex initialization failed\n", 0);
// Throw exception
throw bad_alloc();
}
// Increment the object count
InterlockedIncrement(&numSChannelObjects);
DbgTrace(1, "SChannel::SChannel- End\n", 0);
} /*-- SChannel::SChannel() --*/
//++=======================================================================
SChannel::~SChannel(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "SChannel::~SChannel- Start, Obj = %08X\n", this);
// Cleanup resources allocated for the object
pthread_mutex_destroy(&m_mutex);
// Free connection socket if necessary
if (m_socket != INVALID_SOCKET)
{
shutdown(m_socket, SHUT_RDWR);
struct linger linger_opt = {1, 15};
setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt));
closesocket(m_socket);
}
// Decrement the object count
InterlockedDecrement(&numSChannelObjects);
DbgTrace(1, "SChannel::~SChannel- End\n", 0);
} /*-- SChannel::~SChannel() --*/
//++=======================================================================
int
SChannel::init(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus = -1;
SmartSChannel *pSmartSChannel = NULL;
DbgTrace(1, "SChannel::init- Start, Obj = %08X\n", this);
// Verify the state of the object
if (m_state == State_Connected)
{
// Launch a thread to service the channel connection
try {
// Create a SmartSChannel object to make sure that the object
// does not get deleted prematurely.
pSmartSChannel = new SmartSChannel(this);
// Create the channel connection thread
pthread_t thread;
int threadCreateStatus = pthread_create(&thread,
NULL,
(void*(*)(void*))SChannel::connectionThread,
pSmartSChannel);
if (threadCreateStatus == 0)
{
// We succeeded
retStatus = 0;
}
else
{
DbgTrace(0, "SChannel::init- Unable to create channel connection thread, error = %08X\n", threadCreateStatus);
}
}
catch (...) {
DbgTrace(0, "SChannel::init- Exception caught creating smart pointer\n", 0);
}
}
else
{
DbgTrace(0, "SChannel::init- invalid state, state = %d\n", m_state);
}
// Deal with initialization failures
if (retStatus)
{
// Adjust the object state
m_state = State_FailedInitialization;
// Free SmartSChannel just in case
delete pSmartSChannel;
}
DbgTrace(1, "SChannel::init- End, status = %08X\n", retStatus);
return retStatus;
} /*-- SChannel::init() --*/
//++=======================================================================
void*
SChannel::connectionThread(
SmartPtr<SChannel> *pSmartSChannel)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
SChannel *pSChannel = *pSmartSChannel;
bool doneReceivingData = false;
unsigned long bytesReceived;
unsigned long bytesSent;
uint32_t reqId;
int payloadLength;
unsigned long totalPayloadBytesReceived = 0;
char reqDataPktHdr[ReqDataPktHdrTemplate.length()];
char reqErrorPktHdr[ReqErrorPktHdrTemplate.length()];
char *pRecvBuff;
ServerReq *pServerReq;
DbgTrace(1, "SChannel::connectionThread- Start, Obj = %08X\n", pSChannel);
// Set the thread in the detached state so that it is cleaned up when it exits
pthread_detach(pthread_self());
// Check that we are still connected
if (pSChannel->m_state == State_Connected)
{
// Receive and process channel data
while (!doneReceivingData)
{
DbgTrace(2, "SChannel::connectionThread- Receive Loop, Obj = %08X\n", pSChannel);
// Receive the ReqDataPktHdr. Note, if we add other packet types and if the
// packet types have different header lengths, then we will need to modify
// this code to first receive the packet type and then receive the rest
// of the header based on type.
while (1)
{
bytesReceived = recv(pSChannel->m_socket,
reqDataPktHdr,
ReqDataPktHdrTemplate.length(),
MSG_WAITALL);
if (bytesReceived != SOCKET_ERROR
|| errno != EINTR)
{
break;
}
}
if (bytesReceived != SOCKET_ERROR)
{
// Check if the connection was terminated
if (bytesReceived == ReqDataPktHdrTemplate.length())
{
// Get the reqId and payload length
if (ChannelProto::getReqIdAndPayloadLength(reqDataPktHdr,
sizeof(reqDataPktHdr),
&reqId,
&payloadLength))
{
// Procced based on the packet type
switch (ChannelProto::getPktType(*reqDataPktHdr))
{
case ChannelProto::ReqDataCarrierPacketType:
DbgTrace(2, "SChannel::connectionThread- Processing Request Data Packet, Obj = %08X\n", pSChannel);
// Allocate a buffer big enough to receive the payload. Allow space to NULL terminate.
pRecvBuff = new char[payloadLength + 1];
if (pRecvBuff != NULL)
{
pRecvBuff[payloadLength] = '\0';
// Buffer allocated, receive the Req payload.
while (1)
{
bytesReceived = recv(pSChannel->m_socket,
pRecvBuff,
payloadLength,
MSG_WAITALL);
if (bytesReceived != SOCKET_ERROR
|| errno != EINTR)
{
break;
}
}
if (bytesReceived != SOCKET_ERROR)
{
// Verify that we received all of the payload
if (bytesReceived == payloadLength)
{
// Received all of the payload data
totalPayloadBytesReceived += bytesReceived;
// Instantiate ServerReq object
bool reqProcessingStartedSuccessfully = false;
try {
pServerReq = new ServerReq(pSChannel,
reqId,
pRecvBuff,
bytesReceived);
}
catch (...) {
DbgTrace(0, "SChannel::connectionThread- Exception caught creating ServerReq obj\n", 0);
}
// Acquire exclusive access to the SChannel object
pthread_mutex_lock(&pSChannel->m_mutex);
if (pServerReq)
{
// Forget about the receive buffer
pRecvBuff = NULL;
// Start processing the Request
if (ServiceRequest(pServerReq) != 0)
{
// Failed to start processing of the Request, delete the ServerReq object.
DbgTrace(0, "SChannel::connectionThread- StartRequest failed, Obj = %08X\n", pSChannel);
delete pServerReq;
}
else
{
reqProcessingStartedSuccessfully = true;
}
}
else
{
//DbgTrace(1, "SChannel::connectionThread- Failed to obtain idle ServerReq, Obj = %08X\n", pSChannel);
DbgTrace(0, "SChannel::connectionThread- Failed to obtain idle ServerReq, Obj = %08X\n", pSChannel);
}
// Check if we must send an Request Error packet back to the client
if (reqProcessingStartedSuccessfully == false)
{
// Build ReqErrorHeader
if (ChannelProto::buildReqErrorPktHdr(reqId,
0,
reqErrorPktHdr) == 0)
{
// Packet header was built, now sent it to the client.
bytesSent = send(pSChannel->m_socket,
reqErrorPktHdr,
sizeof(reqErrorPktHdr),
MSG_NOSIGNAL);
if (bytesSent != sizeof(reqErrorPktHdr))
{
DbgTrace(1, "SChannel::connectionThread- Connection aborted prematurely, Obj = %08X\n", pSChannel);
//printf("SChannel::connectionThread- 1Connection aborted prematurely, Obj = %08X\n", pSChannel);
doneReceivingData = true;
}
}
else
{
DbgTrace(0, "SChannel::connectionThread- Error building Req End Pkt Header, Obj = %08X\n", pSChannel);
}
}
// Release exclusive access to the SChannel object
pthread_mutex_unlock(&pSChannel->m_mutex);
}
else
{
DbgTrace(1, "SChannel::connectionThread- Connection aborted prematurely, Obj = %08X\n", pSChannel);
//printf("bytesReceived = %d, payloadLength = %d\n", bytesReceived, payloadLength);
//printf("SChannel::connectionThread- 2Connection aborted prematurely, Obj = %08X\n", pSChannel);
doneReceivingData = true;
}
}
else
{
DbgTrace(1, "SChannel::connectionThread- Connection aborted prematurely, Obj = %08X\n", pSChannel);
//printf("Socket error = %d\n", errno);
//printf("SChannel::connectionThread- 3Connection aborted prematurely, Obj = %08X\n", pSChannel);
doneReceivingData = true;
}
// Free receive buffer if necessary
if (pRecvBuff)
delete[] pRecvBuff;
}
else
{
DbgTrace(0, "SChannel::connectionThread- Unable to allocate receive buffer, Obj = %08X\n", pSChannel);
doneReceivingData = true;
}
break;
default:
DbgTrace(0, "SChannel::connectionThread- Unknown Packet Type, Obj = %08X\n", pSChannel);
doneReceivingData = true;
break;
}
}
else
{
DbgTrace(1, "SChannel::connectionThread- Unable to obtain payload length, Obj = %08X\n", pSChannel);
doneReceivingData = true;
}
}
else
{
DbgTrace(1, "SChannel::connectionThread- The channel connection was terminated, Obj = %08X\n", pSChannel);
//printf("bytesReceived = %d, expected = %d\n", bytesReceived, ReqDataPktHdrTemplate.length());
//printf("SChannel::connectionThread- 4The channel connection was terminated, Obj = %08X\n", pSChannel);
doneReceivingData = true;
}
}
else
{
DbgTrace(1, "SChannel::connectionThread- The channel connection was aborted, Obj = %08X\n", pSChannel);
//printf("Socket error = %d\n", errno);
//printf("SChannel::connectionThread- 5The channel connection was aborted, Obj = %08X\n", pSChannel);
doneReceivingData = true;
}
}
}
// Acquire exclusive access to the SChannel object
pthread_mutex_lock(&pSChannel->m_mutex);
// Try to change the SChannel state to disconnected
if (pSChannel->m_state == State_Connected)
pSChannel->m_state = State_Disconnected;
// Release exclusive access to the SChannel object
pthread_mutex_unlock(&pSChannel->m_mutex);
// Remove ourselves from the SChannel list
RemoveFromSChannelList(pSChannel);
// Free SmartSChannel
delete pSmartSChannel;
DbgTrace(1, "SChannel::connectionThread- End\n", 0);
// Exit
pthread_exit(NULL);
return 0; // never-reached!
} /*-- SChannel::connectionThread() --*/
//++=======================================================================
void
SChannel::closeChannel(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "SChannel::closeChannel- Start, Obj = %08X\n", this);
// Acquire SChannel mutex
pthread_mutex_lock(&m_mutex);
// Switch the socket state to closed
m_state = State_Closed;
// Check if we must close the socket
if (m_socket != INVALID_SOCKET)
{
// Socket needs to be closed, this will
// release the channel connection thread
// if it is active.
shutdown(m_socket, SHUT_RDWR);
struct linger linger_opt = {1, 15};
setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt));
closesocket(m_socket);
m_socket = INVALID_SOCKET;
}
// Release SChannel mutex
pthread_mutex_unlock(&m_mutex);
DbgTrace(1, "SChannel::closeChannel- End\n", 0);
} /*-- SChannel::closeChannel() --*/
//++=======================================================================
int
SChannel::sendReplyData(
uint32_t reqId,
char *pServerData,
int32_t serverDataLen)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
// L2
//=======================================================================--
{
int retStatus = -1;
char reqDataPktHdr[ReqDataPktHdrTemplate.length()];
struct msghdr sendmsgHdr = {0};
struct iovec ioVectors[2];
unsigned long bytesSent;
unsigned long totalBytesSent = 0;
unsigned long bytesToSend = sizeof(reqDataPktHdr) + serverDataLen;
DbgTrace(1, "SChannel::sendReplyData- Start, Obj = %08X\n", this);
// Acquire exclusive access to the channel object
pthread_mutex_lock(&m_mutex);
// Verify that the channel is connected
if (m_state == State_Connected)
{
// Build ReqDataHeader
if (ChannelProto::buildReqDataPktHdr(reqId,
serverDataLen,
reqDataPktHdr) == 0)
{
// Packet header was built, now sent it along with the client data to
// the server.
ioVectors[0].iov_base = reqDataPktHdr;
ioVectors[0].iov_len = sizeof(reqDataPktHdr);
ioVectors[1].iov_base = (char*) pServerData;
ioVectors[1].iov_len = serverDataLen;
sendmsgHdr.msg_iov = ioVectors;
sendmsgHdr.msg_iovlen = 2;
while (1)
{
bytesSent = sendmsg(m_socket,
&sendmsgHdr,
MSG_NOSIGNAL);
if (bytesSent == SOCKET_ERROR)
{
// Check if we were interrupted during the transfer
if (errno == EINTR)
{
// Just try again
continue;
}
// An unrecoverable error was encountered during the send operation,
// assume there was a communication failure. Close the socket to make
// sure that the connectionThread cleans up.
//printf("SChannel::sendReplyData- sendmsgn error, totalBytesSent = %d, bytesToSend = %d, errno = %d\n", totalBytesSent, bytesToSend, errno);
DbgTrace(0, "SChannel::sendReplyData- sendmsgn error, errno = %d\n", errno);
m_state = State_Disconnected;
shutdown(m_socket, SHUT_RDWR);
struct linger linger_opt = {1, 15};
setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt));
closesocket(m_socket);
m_socket = INVALID_SOCKET;
break;
}
else
{
// Account for the bytes sent
totalBytesSent += bytesSent;
// Check if we are done sending all of the data
if (totalBytesSent >= bytesToSend)
{
// We are done
break;
}
else
{
// Adjust the ioVector structure to send data not yet sent
if (totalBytesSent >= sizeof(reqDataPktHdr))
{
// The packet header was sent, use only one ioVector.
int serverDataAlreadySent = totalBytesSent - sizeof(reqDataPktHdr);
ioVectors[0].iov_base = (char*) pServerData + serverDataAlreadySent;
ioVectors[0].iov_len = serverDataLen - serverDataAlreadySent;
sendmsgHdr.msg_iov = ioVectors;
sendmsgHdr.msg_iovlen = 1;
}
else
{
// Not all of the packet header was sent, use two ioVectors.
ioVectors[0].iov_base = (char*) reqDataPktHdr + totalBytesSent;
ioVectors[0].iov_len = sizeof(reqDataPktHdr) - totalBytesSent;
ioVectors[1].iov_base = (char*) pServerData;
ioVectors[1].iov_len = serverDataLen;
sendmsgHdr.msg_iov = ioVectors;
sendmsgHdr.msg_iovlen = 2;
}
}
}
}
// Return success even if the send failed to allow things to be cleaned up
// by the connectionThread routine.
retStatus = 0;
}
else
{
DbgTrace(0, "SChannel::sendReplyData- Error building Req Data Pkt Header, Obj = %08X\n", this);
}
}
else
{
DbgTrace(1, "SChannel::sendReplyData- Channel not connected, state = %08X\n", m_state);
}
// Release exclusive access to the channel object
pthread_mutex_unlock(&m_mutex);
DbgTrace(1, "SChannel::sendReplyData- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- SChannel::sendReplyData() --*/
//++=======================================================================
int
SChannel::sendReplyError(
uint32_t reqId)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
// L2
//=======================================================================--
{
int retStatus = -1;
char reqErrorPktHdr[ReqErrorPktHdrTemplate.length()];
struct msghdr sendmsgHdr = {0};
struct iovec ioVectors[1];
unsigned long bytesSent;
unsigned long totalBytesSent = 0;
unsigned long bytesToSend = sizeof(reqErrorPktHdr);
DbgTrace(1, "SChannel::sendReplyError- Start, Obj = %08X\n", this);
// Acquire exclusive access to the channel object
pthread_mutex_lock(&m_mutex);
// Verify that the channel is connected
if (m_state == State_Connected)
{
// Build ReqErrorHeader
if (ChannelProto::buildReqErrorPktHdr(reqId,
0,
reqErrorPktHdr) == 0)
{
// Packet header was built, now sent it along with the client data to
// the server.
ioVectors[0].iov_base = reqErrorPktHdr;
ioVectors[0].iov_len = sizeof(reqErrorPktHdr);
sendmsgHdr.msg_iov = ioVectors;
sendmsgHdr.msg_iovlen = 1;
while (1)
{
bytesSent = sendmsg(m_socket,
&sendmsgHdr,
MSG_NOSIGNAL);
if (bytesSent == SOCKET_ERROR)
{
// Check if we were interrupted during the transfer
if (errno == EINTR)
{
// Just try again
continue;
}
// An unrecoverable error was encountered during the send operation,
// assume there was a communication failure. Close the socket to make
// sure that the connectionThread cleans up.
//printf("SChannel::sendReplyError- sendmsgn error, totalBytesSent = %d, bytesToSend = %d, errno = %d\n", totalBytesSent, bytesToSend, errno);
DbgTrace(0, "SChannel::sendReplyError- sendmsgn error, errno = %d\n", errno);
m_state = State_Disconnected;
shutdown(m_socket, SHUT_RDWR);
struct linger linger_opt = {1, 15};
setsockopt(m_socket, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt));
closesocket(m_socket);
m_socket = INVALID_SOCKET;
break;
}
else
{
// Account for the bytes sent
totalBytesSent += bytesSent;
// Check if we are done sending all of the data
if (totalBytesSent >= bytesToSend)
{
// We are done
break;
}
else
{
// Adjust the ioVector structure to send data not yet sent
ioVectors[0].iov_base = (char*) reqErrorPktHdr + totalBytesSent;
ioVectors[0].iov_len = sizeof(reqErrorPktHdr) - totalBytesSent;
sendmsgHdr.msg_iov = ioVectors;
sendmsgHdr.msg_iovlen = 1;
}
}
}
// Return success even if the send failed to allow things to be cleaned up
// by the connectionThread routine.
retStatus = 0;
}
else
{
DbgTrace(0, "SChannel::sendReplyError- Error building Req Data Pkt Header, Obj = %08X\n", this);
}
}
else
{
DbgTrace(1, "SChannel::sendReplyError- Channel not connected, state = %08X\n", m_state);
}
// Release exclusive access to the channel object
pthread_mutex_unlock(&m_mutex);
DbgTrace(1, "SChannel::sendReplyError- End, retStatus = %08X\n", retStatus);
return retStatus;
} /*-- SChannel::sendReplyError() --*/
//=========================================================================
//=========================================================================

View File

@ -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>
*
***********************************************************************/
#ifndef _SCHANNEL_
#define _SCHANNEL_
//===[ Include files ]=====================================================
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//===[ Type definitions ]==================================================
// Forward reference
class ServerReq;
//
// SChannel Class Definition
//
class SChannel : public ObjRef
{
// Object State
enum ChannelStates
{
State_FailedInitialization = 1,
State_Connected,
State_Disconnected,
State_Closed
};
ChannelStates m_state;
// Connection socket
int m_socket;
// Synchronization variables
pthread_mutex_t m_mutex;
//
// Server Request Map - This map contains all of the active ServerReq objects.
// The key used to obtain ServerReq object in the map
// is the Request Id.
//
typedef map<uint32_t, ServerReq*> RSMap;
typedef RSMap::iterator RSMapIter;
typedef pair<RSMapIter, bool> RSIterBoolPair;
RSMap m_rsMap;
//
// Service connection thread procedure
//
// Parameters:
// pSmartSChannel (input) -
// Pointer to SmartPtr<SChannel> object.
//
// Abstract: Thread in charge of servicing channel connection.
//
// Returns: Nothing.
//
static void* connectionThread(SmartPtr<SChannel> *pSmartSChannel);
public:
//
// Constructor
//
// Parameters:
// connSocket (input) -
// Socket for channel connection.
//
// Abstract: Constructs SChannel object.
//
// Returns: Nothing.
//
SChannel(int connSocket);
//
// Destructor
~SChannel(void);
//
// Initialization routine
//
// Parameters: None.
//
// Abstract: Initializes SChannel object.
//
// Returns: 0 if successful.
//
int init(void);
//
// Close channel routine
//
// Parameters: None.
//
// Abstract: Closes the channel.
//
// Returns: Nothing.
//
void closeChannel(void);
//
// Send Reply Data routine
//
// Parameters:
// reqId (input) -
// Request Id.
//
// pServerData (input) -
// Pointer to server data that must be sent to
// the client. Buffer is NOT released by the
// procedure.
//
// serverDataLen (input) -
// Length of the server data.
//
// Abstract: Sends data to the client for active Request.
//
// Returns: 0 if successful.
//
int sendReplyData(uint32_t reqId,
char *pServerData,
int32_t serverDataLen);
//
// Send Reply Error routine
//
// Parameters:
// reqId (input) -
// Request Id.
//
// Abstract: Indicates to the client that the request was
// not processed successfully..
//
// Returns: 0 if successful.
//
int sendReplyError(uint32_t reqId);
};
typedef SmartPtr<SChannel> SmartSChannel;
//===[ Function prototypes ]===============================================
#endif // _SCHANNEL_
//=========================================================================
//=========================================================================

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,225 @@
/***********************************************************************
*
* 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 "ipcint.h"
#include "schannel.h"
#include "serverreq.h"
#include <assert.h> // Ensure that NDEBUG is defined for release builds!
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
#define SERVER_REQ_SIGNATURE 0x52525653 // SVRR
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//
// Object Counters
//
unsigned long numServerReqObjects = 0;
//++=======================================================================
ServerReq::ServerReq(
SChannel *pSChannel,
uint32_t reqId,
char *pClientData,
int32_t clientDataLength) :
m_signature (SERVER_REQ_SIGNATURE),
m_reqId (reqId),
m_pClientData (pClientData),
m_clientDataLength (clientDataLength)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ServerReq::ServerReq- Start, Obj = %08X\n", this);
// Create a SmartSChannel object to keep the SChannel object from
// going away while we process the request.
m_pSmartSChannel = new SmartSChannel(pSChannel);
// Increment the object count
InterlockedIncrement(&numServerReqObjects);
DbgTrace(1, "ServerReq::ServerReq- End\n", 0);
} /*-- ServerReq::ServerReq() --*/
//++=======================================================================
ServerReq::~ServerReq(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ServerReq::~ServerReq- Start, Obj = %08X\n", this);
// Free any client data that may be hanging around
if (m_pClientData)
free(m_pClientData);
// Delete the SmartSChannel
delete m_pSmartSChannel;
// Decrement the object count
InterlockedDecrement(&numServerReqObjects);
DbgTrace(1, "ServerReq::~ServerReq- End\n", 0);
} /*-- ServerReq::~ServerReq() --*/
//++=======================================================================
int
ServerReq::getReqData(
char **ppClientData)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ServerReq::getReqData- Start, Obj = %08X\n", this);
#if DEBUG
assert(m_signature == SERVER_REQ_SIGNATURE);
#endif
// Return pointer to the client data
*ppClientData = m_pClientData;
DbgTrace(1, "ServerReq::getReqData- End, reqDataLen = %08X\n", m_clientDataLength);
return m_clientDataLength;
}
//++=======================================================================
void
ServerReq::complete(
char *pServerData)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
SChannel *pSChannel = *m_pSmartSChannel;
DbgTrace(1, "ServerReq::complete- Start, Obj = %08X\n", this);
#if DEBUG
assert(m_signature == SERVER_REQ_SIGNATURE);
#endif
// Send data to the client
pSChannel->sendReplyData(m_reqId,
pServerData,
strlen(pServerData));
DbgTrace(1, "ServerReq::complete- End\n", 0);
} /*-- ServerReq::complete() --*/
//++=======================================================================
void
ServerReq::abort(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
SChannel *pSChannel = *m_pSmartSChannel;
DbgTrace(1, "ServerReq::abort- Start, Obj = %08X\n", this);
#if DEBUG
assert(m_signature == SERVER_REQ_SIGNATURE);
#endif
// Send an error to the client
pSChannel->sendReplyError(m_reqId);
DbgTrace(1, "ServerReq::abort- End\n", 0);
} /*-- ServerReq::abort() --*/
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,145 @@
/***********************************************************************
*
* 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 _SERVERREQ_
#define _SERVERREQ_
//===[ Include files ]=====================================================
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//===[ Type definitions ]==================================================
//
// Server Request Class
//
class ServerReq
{
// Signature
unsigned long m_signature;
// Id of request being processed
uint32_t m_reqId;
// SmartSChannel object pointer for request being processed.
SmartSChannel *m_pSmartSChannel;
// Request Client Data
char *m_pClientData;
int32_t m_clientDataLength;
public:
//
// Destructor
~ServerReq(void);
//
// Constructor
//
// Parameters:
// pSChannel (input) -
// Pointer to SChannel object.
//
// reqId (input) -
// Request Id.
//
// pClientData (input) -
// Pointer to buffer containing the client data.
// Buffer is released when the object is destroyed.
//
// clientDataLength (input) -
// Length of the client data.
//
// Abstract: Constructs ServerReq object.
//
// Returns: Nothing.
//
ServerReq(SChannel *pSChannel,
uint32_t reqId,
char *pClientData,
int32_t clientDataLength);
//
// Get request Data routine
//
// Parameters:
// ppClientData (input/output) -
// Pointer to variable that will receive pointer to
// data sent by the client. Buffer should NOT released by
// caller.
//
// Abstract: Sends the requests reply data to the client.
//
// Returns: The length of the client request data. 0 if not successful.
//
int getReqData(char **ppClientData);
//
// Complete Request routine
//
// Parameters:
// pServerData (input) -
// Pointer to server data that must be sent to
// the client. Buffer is NOT released by the
// procedure.
//
// Abstract: Completes the request.
//
// Returns: Nothing.
//
void complete(char *pServerData);
//
// Abort Request routine
//
// Parameters: None.
//
// Abstract: Aborts the request.
//
// Returns: Nothing.
//
void abort(void);
};
//===[ Function prototypes ]===============================================
#endif // _SERVERREQ_
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,181 @@
/***********************************************************************
*
* 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 "ipcint.h"
#include "serverthread.h"
#include <assert.h> // Ensure that NDEBUG is defined for release builds!
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
#define SERVER_THREAD_SIGNATURE 0x54525653 // SVRT
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//
// Object Counters
//
unsigned long numServerThreadObjects = 0;
//++=======================================================================
ServerThread::ServerThread(void) :
m_signature (SERVER_THREAD_SIGNATURE)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ServerThread::ServerThread- Start, Obj = %08X\n", this);
// Initialize the condition
if (pthread_cond_init(&m_condition, NULL) != 0)
{
DbgTrace(0, "ServerThread::ServerThread- Condition initialization failed\n", 0);
// Throw exception
throw bad_alloc();
}
// Increment the object count
InterlockedIncrement(&numServerThreadObjects);
DbgTrace(1, "ServerThread::ServerThread- End\n", 0);
} /*-- ServerThread::ServerThread() --*/
//++=======================================================================
ServerThread::~ServerThread(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ServerThread::~ServerThread- Start, Obj = %08X\n", this);
// Cleanup resources allocated for the object
pthread_cond_destroy(&m_condition);
// Decrement the object count
InterlockedDecrement(&numServerThreadObjects);
DbgTrace(1, "ServerThread::~ServerThread- End\n", 0);
} /*-- ServerThread::~ServerThread() --*/
//++=======================================================================
void
ServerThread::awaken(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ServerThread::awaken- Start, Obj = %08X\n", this);
#if DEBUG
assert(m_signature == SERVER_THREAD_SIGNATURE);
#endif
// Signal ourselves to wake up
pthread_cond_signal(&m_condition);
DbgTrace(1, "ServerThread::awaken- End\n", 0);
} /*-- ServerThread::awaken() --*/
//++=======================================================================
void
ServerThread::suspend(
pthread_mutex_t *pMutex)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace(1, "ServerThread::suspend- Start, Obj = %08X\n", this);
#if DEBUG
assert(m_signature == SERVER_THREAD_SIGNATURE);
#endif
// Wait until signaled to awaken
pthread_cond_wait(&m_condition, pMutex);
DbgTrace(1, "ServerThread::suspend- End\n", 0);
} /*-- ServerThread::suspend() --*/
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,107 @@
/***********************************************************************
*
* 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 _SERVERTHREAD_
#define _SERVERTHREAD_
//===[ Include files ]=====================================================
//===[ External data ]=====================================================
//===[ External prototypes ]===============================================
//===[ Manifest constants ]================================================
//===[ Type definitions ]==================================================
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
//===[ Type definitions ]==================================================
//
// Server Thread Class
//
class ServerThread
{
// Signature
unsigned long m_signature;
// Synchronization variable
pthread_cond_t m_condition;
public:
//
// Destructor
~ServerThread(void);
//
// Constructor
//
// Parameters: None.
//
// Abstract: Constructs ServerThread object.
//
// Returns: Nothing.
//
ServerThread(void);
//
// Awaken ServerThread routine
//
// Parameters: None.
//
// Abstract: Awakens a ServerThread.
//
// Returns: Nothing.
//
void awaken(void);
//
// Suspend ServerThread routine
//
// Parameters:
// pMutex (input) -
// Pointer to mutex to associate with
// condition used for waiting..
//
// Abstract: Suspends a ServerThread.
//
// Returns: Nothing.
//
void suspend(pthread_mutex_t *pMutex);
};
//===[ Function prototypes ]===============================================
#endif // _SERVERTHREAD_
//=========================================================================
//=========================================================================

View File

@ -0,0 +1,3 @@
#!/bin/bash
gcc -o TestServer testServer.c -g -I../../../../../include -L../../../../../lib/Release -lpthread -lcasa_s_ipc -Xlinker -rpath -Xlinker ../../../../../lib/Release

View File

@ -0,0 +1,311 @@
/***********************************************************************
*
* 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 <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <pthread.h>
#include <unistd.h>
#include <stdint.h>
#include "casa_s_ipc.h"
//===[ Type definitions ]==================================================
//
// DbgTrace macro define
//
#define DbgTrace(LEVEL, X, Y) { \
if (LEVEL == 0) \
printf(X, Y); \
else if (DebugLevel >= LEVEL) \
printf(X, Y); \
}
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
// Usage string
char usage[] = "\nTest: usage: -l lifetime [-D DebugLevel]\n";
int DebugLevel = 3;
// Test lifetime
int testLifetime = 60; // Seconds
bool processingRequests = true;
//++=======================================================================
void* UnInitThread()
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
DbgTrace(1, "UnInitThread- Start\n", 0);
// Sleep for the configured amount
sleep(testLifetime);
// Stop processing Rpc Requests
processingRequests = false;
// Un-init the Svc Rpc Service Subsystem
IpcServerShutdown();
DbgTrace(1, "UnInitThread- End\n", 0);
// Exit
pthread_exit(NULL);
return 0; // never-reached!
}
//++=======================================================================
void* ProcessRequestThread(int32_t requestId)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
char *pReqData = NULL;
DbgTrace(1, "ProcessRequestThread- Start\n", 0);
// Get the rpc data
int dataLen = IpcServerGetRequestData(requestId, &pReqData);
if (dataLen != 0)
{
// Just echo the data back as the reply
IpcServerCompleteRequest(requestId,pReqData);
}
else
{
DbgTrace(0, "ProcessRequestThread- Error obtaining Request data\n", 0);
IpcServerAbortRequest(requestId);
}
DbgTrace(1, "ProcessRequestThread- End\n", 0);
// Exit
pthread_exit(NULL);
return 0; // never-reached!
}
//++=======================================================================
void
ExecuteTests(void)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// Environment:
//
//=======================================================================--
{
pthread_t thread;
int threadCreateStatus;
DbgTrace(1, "ExecuteTests- Start\n", 0);
// Initialize the Svc Ipc Subsystem
if (IpcServerInit("TestServer",
DebugLevel,
false) == 0)
{
// Set the server listen address
if (IpcServerSetInAddress(5000) == 0)
{
// Now start servicing requests.
if (IpcServerStart() == 0)
{
// The Ipc subsystem was started, now create a thread for
// un-initializing the Ipc subsystem after a while.
threadCreateStatus = pthread_create(&thread,
NULL,
(void*(*)(void*))UnInitThread,
(void*)NULL);
if (threadCreateStatus != 0)
{
DbgTrace(0, "ExecuteTests- Unable to create un-initialization thread, error = %08X\n", threadCreateStatus);
IpcServerShutdown();
}
else
{
// Process Incoming Requests
while (processingRequests)
{
int32_t requestId = IpcServerGetRequest();
if (requestId != 0)
{
// Create a thread to handle the request
threadCreateStatus = pthread_create(&thread,
NULL,
(void*(*)(void*))ProcessRequestThread,
(void*)requestId);
if (threadCreateStatus != 0)
{
DbgTrace(0, "ExecuteTests- Unable to create process request thread, error = %08X\n", threadCreateStatus);
IpcServerAbortRequest(requestId);
}
}
else
{
// No need to service requests any longer
break;
}
}
}
}
else
{
DbgTrace(0, "ExecuteTests- Error starting the Ipc subsystem\n", 0);
IpcServerShutdown();
}
}
else
{
DbgTrace(0, "ExecuteTests- Error setting server address\n", 0);
IpcServerShutdown();
}
}
else
{
DbgTrace(0, "ExecuteTests- Ipc subsystem initialization failed\n", 0);
}
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("**** Ipc Server test ****\n");
// Scan through the options specified
while (!doneScanning)
{
opterr = 0;
option = getopt(argc, argv, "l: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 'l':
// Set the test lifetime
printf("Lifetime = %s\n", optarg);
testLifetime = atoi(optarg);
optionsSpecified++;
break;
case '?':
// Invalid option detected
doneScanning = true;
invalidOption = true;
break;
default:
// Done scanning
doneScanning = true;
break;
}
}
// Do some sanity checking
if (!invalidOption)
{
ExecuteTests();
}
else
{
// Invalid option detected
printf(usage, argv[0]);
}
return 0;
} /*-- main() --*/

View File

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