diff --git a/CASA-auth-token/server/AUTHORS b/CASA-auth-token/server/AUTHORS new file mode 100644 index 00000000..ba13017c --- /dev/null +++ b/CASA-auth-token/server/AUTHORS @@ -0,0 +1,2 @@ +Juan Carlos Luciani - jluciani@novell.com + diff --git a/CASA-auth-token/server/ApacheSupport/2.2/Makefile.am b/CASA-auth-token/server/ApacheSupport/2.2/Makefile.am new file mode 100644 index 00000000..a9fff5ba --- /dev/null +++ b/CASA-auth-token/server/ApacheSupport/2.2/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/ApacheSupport/2.2/README b/CASA-auth-token/server/ApacheSupport/2.2/README new file mode 100644 index 00000000..bde7ef2f --- /dev/null +++ b/CASA-auth-token/server/ApacheSupport/2.2/README @@ -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 + * + ***********************************************************************/ +/*********************************************************************** + * + * 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: + + + SetHandler example-handler + AuthType Basic + AuthName "CASA-Authentication" + AuthBasicProvider casa + Require valid-user + + +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. + + + + + + + + + + diff --git a/CASA-auth-token/server/ApacheSupport/2.2/TODO b/CASA-auth-token/server/ApacheSupport/2.2/TODO new file mode 100644 index 00000000..4145a4af --- /dev/null +++ b/CASA-auth-token/server/ApacheSupport/2.2/TODO @@ -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. diff --git a/CASA-auth-token/server/ApacheSupport/2.2/linux/Makefile.am b/CASA-auth-token/server/ApacheSupport/2.2/linux/Makefile.am new file mode 100644 index 00000000..04bcce2e --- /dev/null +++ b/CASA-auth-token/server/ApacheSupport/2.2/linux/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/ApacheSupport/2.2/mod_authn_casa.c b/CASA-auth-token/server/ApacheSupport/2.2/mod_authn_casa.c new file mode 100644 index 00000000..a0bb0342 --- /dev/null +++ b/CASA-auth-token/server/ApacheSupport/2.2/mod_authn_casa.c @@ -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 + * + ***********************************************************************/ + +#include + +#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 +}; diff --git a/CASA-auth-token/server/ApacheSupport/Makefile.am b/CASA-auth-token/server/ApacheSupport/Makefile.am new file mode 100644 index 00000000..5478d49a --- /dev/null +++ b/CASA-auth-token/server/ApacheSupport/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/AuthTokenValidate/Makefile.am b/CASA-auth-token/server/AuthTokenValidate/Makefile.am new file mode 100644 index 00000000..23bc78d3 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/AuthTokenValidate/README b/CASA-auth-token/server/AuthTokenValidate/README new file mode 100644 index 00000000..3f247a06 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/README @@ -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 + * + ***********************************************************************/ +/*********************************************************************** + * + * 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. + + + + + + + + + + diff --git a/CASA-auth-token/server/AuthTokenValidate/Svc/Makefile.am b/CASA-auth-token/server/AuthTokenValidate/Svc/Makefile.am new file mode 100644 index 00000000..6184e626 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/Svc/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/AuthTokenValidate/Svc/README b/CASA-auth-token/server/AuthTokenValidate/Svc/README new file mode 100644 index 00000000..84da76dc --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/Svc/README @@ -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 + * + ***********************************************************************/ +/*********************************************************************** + * + * 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. + + + + + + + + + diff --git a/CASA-auth-token/server/AuthTokenValidate/Svc/TODO b/CASA-auth-token/server/AuthTokenValidate/Svc/TODO new file mode 100644 index 00000000..a6cb6c81 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/Svc/TODO @@ -0,0 +1,13 @@ +/*********************************************************************** + * + * TODO for CasaAuthtokenValidateD + * + ***********************************************************************/ + +INTRODUCTION + +This file contains a list of the items still outstanding for CasaAuthtokenValidateD. + +OUTSTANDING ITEMS + +None. diff --git a/CASA-auth-token/server/AuthTokenValidate/Svc/linux/CasaAuthtokenValidateD b/CASA-auth-token/server/AuthTokenValidate/Svc/linux/CasaAuthtokenValidateD new file mode 100644 index 00000000..eb783715 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/Svc/linux/CasaAuthtokenValidateD @@ -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 " > /dev/stderr + RVAL=1 + ;; +esac + +rc_failed $RVAL +rc_status -v +rc_exit + diff --git a/CASA-auth-token/server/AuthTokenValidate/Svc/linux/Makefile.am b/CASA-auth-token/server/AuthTokenValidate/Svc/linux/Makefile.am new file mode 100644 index 00000000..c0328f44 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/Svc/linux/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/AuthTokenValidate/Svc/linux/envvars b/CASA-auth-token/server/AuthTokenValidate/Svc/linux/envvars new file mode 100644 index 00000000..b04f9f15 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/Svc/linux/envvars @@ -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 + diff --git a/CASA-auth-token/server/AuthTokenValidate/Svc/linux/internal.h b/CASA-auth-token/server/AuthTokenValidate/Svc/linux/internal.h new file mode 100644 index 00000000..69c94c03 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/Svc/linux/internal.h @@ -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 + * + ***********************************************************************/ + +#ifndef _IPCINT_ +#define _IPCINT_ + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +using namespace std; + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // Ensure that NDEBUG is defined for release builds! +#include +#include +} + +//===[ 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_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/server/AuthTokenValidate/Svc/linux/server.cpp b/CASA-auth-token/server/AuthTokenValidate/Svc/linux/server.cpp new file mode 100644 index 00000000..34df8b37 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/Svc/linux/server.cpp @@ -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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" +#include + +//===[ 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() --*/ + + +//========================================================================= +//========================================================================= + + diff --git a/CASA-auth-token/server/AuthTokenValidate/TODO b/CASA-auth-token/server/AuthTokenValidate/TODO new file mode 100644 index 00000000..730eb6f1 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/TODO @@ -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. diff --git a/CASA-auth-token/server/AuthTokenValidate/config.c b/CASA-auth-token/server/AuthTokenValidate/config.c new file mode 100644 index 00000000..0fe71332 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/config.c @@ -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 + * + ***********************************************************************/ + + +//===[ 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); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/server/AuthTokenValidate/config_if.h b/CASA-auth-token/server/AuthTokenValidate/config_if.h new file mode 100644 index 00000000..0cdf31ce --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/config_if.h @@ -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 + * + ***********************************************************************/ + + +#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_ + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/Makefile.am b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/Makefile.am new file mode 100644 index 00000000..2fb64053 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/Makefile.am b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/Makefile.am new file mode 100644 index 00000000..331523b2 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/README b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/README new file mode 100644 index 00000000..6fdccf88 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/README @@ -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 + * + ***********************************************************************/ +/*********************************************************************** + * + * 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. + + + + + + + + + + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/TODO b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/TODO new file mode 100644 index 00000000..1a79afa0 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/TODO @@ -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. diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/identoken.c b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/identoken.c new file mode 100644 index 00000000..f9636b6b --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/identoken.c @@ -0,0 +1,1458 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "internal.h" + +//===[ Type definitions ]================================================== + +// +// XML Constants for the CASA Identity Token +// +#define CASA_IDENT_TOKEN_ELEMENT_NAME "casa_ident_tok" +#define ID_ELEMENT_NAME "id" +#define SOURCE_NAME_ELEMENT_NAME "source_name" +#define SOURCE_URL_ELEMENT_NAME "source_url" +#define TARGET_SERVICE_ELEMENT_NAME "target_service" +#define TARGET_HOST_ELEMENT_NAME "target_host" +#define ATTRIBUTES_ELEMENT_NAME "attributes" + +// +// Parse states +// +#define AWAITING_ROOT_ELEMENT_START 0x0 +#define AWAITING_ROOT_ELEMENT_END 0x1 +#define AWAITING_ID_DATA 0x2 +#define AWAITING_ID_ELEMENT_START 0x3 +#define AWAITING_ID_ELEMENT_END 0x4 +#define AWAITING_SOURCE_NAME_DATA 0x5 +#define AWAITING_SOURCE_NAME_ELEMENT_START 0x6 +#define AWAITING_SOURCE_NAME_ELEMENT_END 0x7 +#define AWAITING_SOURCE_URL_DATA 0x8 +#define AWAITING_SOURCE_URL_ELEMENT_START 0x9 +#define AWAITING_SOURCE_URL_ELEMENT_END 0xA +#define AWAITING_TARGET_SERVICE_DATA 0xB +#define AWAITING_TARGET_SERVICE_ELEMENT_START 0xC +#define AWAITING_TARGET_SERVICE_ELEMENT_END 0xD +#define AWAITING_TARGET_HOST_DATA 0xE +#define AWAITING_TARGET_HOST_ELEMENT_START 0xF +#define AWAITING_TARGET_HOST_ELEMENT_END 0x10 +#define AWAITING_ATTRIBUTES_ELEMENT_START 0x11 +#define AWAITING_ATTRIBUTE_DATA 0x12 +#define AWAITING_ATTRIBUTE_START 0x13 +#define AWAITING_ATTRIBUTE_END 0x14 +#define DONE_PARSING 0x15 + +// +// Attribute structure +// +typedef struct _Attribute +{ + LIST_ENTRY listEntry; + char *pAttribName; + int attribNameLen; + char *pAttribValue; + int attribValueLen; + +} Attribute, *PAttribute; + + +// +// Identity Token Interface instance data +// +typedef struct _IdenTokenIfInstance +{ + int refCount; + char *pIdentId; + int identIdLen; + char *pIdentSourceName; + int identSourceNameLen; + char *pIdentSourceUrl; + int identSourceUrlLen; + char *pTargetService; + int targetServiceLen; + char *pTargetHost; + int targetHostLen; + LIST_ENTRY attributeListHead; + IdenTokenIf idenTokenIf; + +} IdenTokenIfInstance, *PIdenTokenIfInstance; + + +// +// Identity Token Parse Structure +// +typedef struct _IdenTokenParse +{ + XML_Parser p; + int state; + int elementDataProcessed; + IdenTokenIfInstance *pIdenTokenIfInstance; + CasaStatus status; + +} IdenTokenParse, *PIdenTokenParse; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// IdenTokenIf variables +static +int g_numIdenTokenIfObjs = 0; + +// Synchronization mutex +static +HANDLE g_idenTokenIfMutex = NULL; + + +//++======================================================================= +static +void +FreeIdenTokenIfInstance( + IN IdenTokenIfInstance *pIdenTokenIfInstance) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + LIST_ENTRY *pListEntry; + + DbgTrace(2, "-FreeIdenTokenIfInstance- Start\n", 0); + + // Free all of the resources associated with the IdenTokenIfInstance + if (pIdenTokenIfInstance->pIdentId) + free(pIdenTokenIfInstance->pIdentId); + + if (pIdenTokenIfInstance->pIdentSourceName) + free(pIdenTokenIfInstance->pIdentSourceName); + + if (pIdenTokenIfInstance->pIdentSourceUrl) + free(pIdenTokenIfInstance->pIdentSourceUrl); + + if (pIdenTokenIfInstance->pTargetService) + free(pIdenTokenIfInstance->pTargetService); + + if (pIdenTokenIfInstance->pTargetHost) + free(pIdenTokenIfInstance->pTargetHost); + + // Go through all of the associated attributes + pListEntry = pIdenTokenIfInstance->attributeListHead.Flink; + while (pListEntry != &pIdenTokenIfInstance->attributeListHead) + { + Attribute *pAttribute = CONTAINING_RECORD(pListEntry, Attribute, listEntry); + + // Free resources associated with the attribute + if (pAttribute->pAttribName) + free(pAttribute->pAttribName); + + if (pAttribute->pAttribValue) + free(pAttribute->pAttribValue); + + // Forget about this attribute + RemoveEntryList(&pAttribute->listEntry); + free(pAttribute); + + // Start from the top again + pListEntry = pIdenTokenIfInstance->attributeListHead.Flink; + } + + // Free the identity token if instance structure + free(pIdenTokenIfInstance); + + DbgTrace(2, "-FreeIdenTokenIfInstance- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +IdenTokenStartElementHandler( + IN void *pUserData, + IN const XML_Char *name, + IN const XML_Char **atts) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + IdenTokenParse *pIdenTokenParse = (IdenTokenParse*) pUserData; + Attribute *pAttribute; + + DbgTrace(2, "-IdenTokenStartElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pIdenTokenParse->state) + { + case AWAITING_ROOT_ELEMENT_START: + + // In this state, we are only expecting the CASA Identity + // Token Element. + if (strcmp(name, CASA_IDENT_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ID_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ID_ELEMENT_START: + + // In this state, we are only expecting the ID Element. + if (strcmp(name, ID_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ID_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_NAME_ELEMENT_START: + + // In this state, we are only expecting the Source Name Element. + if (strcmp(name, SOURCE_NAME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_SOURCE_NAME_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_URL_ELEMENT_START: + + // In this state, we are only expecting the Source Url Element. + if (strcmp(name, SOURCE_URL_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_SOURCE_URL_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_SERVICE_ELEMENT_START: + + // In this state, we are only expecting the Target Service Element. + if (strcmp(name, TARGET_SERVICE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_TARGET_SERVICE_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_HOST_ELEMENT_START: + + // In this state, we are only expecting the Target Host Element. + if (strcmp(name, TARGET_HOST_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_TARGET_HOST_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ATTRIBUTES_ELEMENT_START: + + // In this state, we are only expecting the Attributes Element. + if (strcmp(name, ATTRIBUTES_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ATTRIBUTE_START; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ATTRIBUTE_START: + + // Allocate an initialize Attribute structure + pAttribute = malloc(sizeof(*pAttribute)); + if (pAttribute) + { + memset(pAttribute, 0, sizeof(*pAttribute)); + InsertTailList(&pIdenTokenParse->pIdenTokenIfInstance->attributeListHead, + &pAttribute->listEntry); + + // Now save the attribute name + pAttribute->attribNameLen = strlen(name) + 1; + pAttribute->pAttribName = malloc(pAttribute->attribNameLen); + if (pAttribute->pAttribName) + { + strcpy(pAttribute->pAttribName, name); + + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ATTRIBUTE_DATA; + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Buffer allocation failure\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + } + else + { + DbgTrace(0, "-IdenTokenStartElementHandler- Buffer allocation failure\n", 0); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected state = %d\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-IdenTokenStartElementHandler- End\n", 0); +} + + +//++======================================================================= +static +CasaStatus +ConsumeElementData( + IN IdenTokenParse *pIdenTokenParse, + IN const XML_Char *s, + IN int len, + INOUT char **ppElementData, + INOUT int *pElementDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + + DbgTrace(3, "-ConsumeElementData- Start\n", 0); + + // Proceed based on whether or not we have already consumed data + // for this element. + if (*ppElementData == NULL) + { + // We have not yet consumed data for this element + pIdenTokenParse->elementDataProcessed = len; + + // Allocate a buffer to hold this element data (null terminated). + *ppElementData = (char*) malloc(len + 1); + if (*ppElementData) + { + memset(*ppElementData, 0, len + 1); + memcpy(*ppElementData, s, len); + + // Return the length of the element data buffer + *pElementDataLen = pIdenTokenParse->elementDataProcessed + 1; + } + else + { + DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + char *pNewBuf; + + // We have already received token data, append this data to it. + pNewBuf = (char*) malloc(pIdenTokenParse->elementDataProcessed + len + 1); + if (pNewBuf) + { + memset(pNewBuf, + 0, + pIdenTokenParse->elementDataProcessed + len + 1); + memcpy(pNewBuf, + *ppElementData, + pIdenTokenParse->elementDataProcessed); + memcpy(pNewBuf + pIdenTokenParse->elementDataProcessed, s, len); + pIdenTokenParse->elementDataProcessed += len; + + // Swap the buffers + free(*ppElementData); + *ppElementData = pNewBuf; + + // Return the length of the element data buffer + *pElementDataLen = pIdenTokenParse->elementDataProcessed + 1; + } + else + { + DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + + DbgTrace(3, "-ConsumeElementData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +void XMLCALL +IdenTokenCharDataHandler( + IN void *pUserData, + IN const XML_Char *s, + IN int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + IdenTokenParse *pIdenTokenParse = (IdenTokenParse*) pUserData; + Attribute *pAttribute; + + DbgTrace(2, "-IdenTokenCharDataHandler- Start\n", 0); + + // Just exit if being called to process LF and CR characters + if (len == 1 + && ((*s == '\n') || (*s == '\r'))) + { + goto exit; + } + + // Proceed based on the state + switch (pIdenTokenParse->state) + { + case AWAITING_ID_DATA: + case AWAITING_ID_ELEMENT_END: + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pIdenTokenParse->pIdenTokenIfInstance->pIdentId, + &pIdenTokenParse->pIdenTokenIfInstance->identIdLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_ID_ELEMENT_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_NAME_DATA: + case AWAITING_SOURCE_NAME_ELEMENT_END: + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pIdenTokenParse->pIdenTokenIfInstance->pIdentSourceName, + &pIdenTokenParse->pIdenTokenIfInstance->identSourceNameLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_SOURCE_NAME_ELEMENT_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_URL_DATA: + case AWAITING_SOURCE_URL_ELEMENT_END: + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pIdenTokenParse->pIdenTokenIfInstance->pIdentSourceUrl, + &pIdenTokenParse->pIdenTokenIfInstance->identSourceUrlLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_SOURCE_URL_ELEMENT_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_SERVICE_DATA: + case AWAITING_TARGET_SERVICE_ELEMENT_END: + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pIdenTokenParse->pIdenTokenIfInstance->pTargetService, + &pIdenTokenParse->pIdenTokenIfInstance->targetServiceLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_TARGET_SERVICE_ELEMENT_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_HOST_DATA: + case AWAITING_TARGET_HOST_ELEMENT_END: + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pIdenTokenParse->pIdenTokenIfInstance->pTargetHost, + &pIdenTokenParse->pIdenTokenIfInstance->targetHostLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_TARGET_HOST_ELEMENT_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ATTRIBUTE_DATA: + case AWAITING_ATTRIBUTE_END: + + // Get a pointer to current attribute structure + pAttribute = CONTAINING_RECORD(pIdenTokenParse->pIdenTokenIfInstance->attributeListHead.Blink, + Attribute, + listEntry); + + pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse, + s, + len, + &pAttribute->pAttribValue, + &pAttribute->attribValueLen); + if (CASA_SUCCESS(pIdenTokenParse->status)) + { + // Advanced to the next state + pIdenTokenParse->state = AWAITING_ATTRIBUTE_END; + } + else + { + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-IdenTokenCharDataHandler- Un-expected state = %d\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + break; + } + +exit: + + DbgTrace(2, "-IdenTokenCharDataHandler- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +IdenTokenEndElementHandler( + IN void *pUserData, + IN const XML_Char *name) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + IdenTokenParse *pIdenTokenParse = (IdenTokenParse*) pUserData; + + DbgTrace(2, "-IdenTokenEndElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pIdenTokenParse->state) + { + case AWAITING_ROOT_ELEMENT_END: + + // In this state, we are only expecting the CASA Identity + // Token Element. + if (strcmp(name, CASA_IDENT_TOKEN_ELEMENT_NAME) == 0) + { + // Done. + pIdenTokenParse->state = DONE_PARSING; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ID_ELEMENT_END: + + // In this state, we are only expecting the Id Element. + if (strcmp(name, ID_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_SOURCE_NAME_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_NAME_ELEMENT_END: + + // In this state, we are only expecting the Source Name Element. + if (strcmp(name, SOURCE_NAME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_SOURCE_URL_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_SOURCE_URL_ELEMENT_END: + + // In this state, we are only expecting the Source URL Element. + if (strcmp(name, SOURCE_URL_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_TARGET_SERVICE_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_SERVICE_ELEMENT_END: + + // In this state, we are only expecting the Target Service Element. + if (strcmp(name, TARGET_SERVICE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_TARGET_HOST_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_TARGET_HOST_ELEMENT_END: + + // In this state, we are only expecting the Target Host Element. + if (strcmp(name, TARGET_HOST_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ATTRIBUTES_ELEMENT_START; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + case AWAITING_ATTRIBUTE_END: + + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ATTRIBUTE_START; + break; + + case AWAITING_ATTRIBUTE_START: + + // We should we done with the attributes, in this state we are only expecting + // the Attributes element. + if (strcmp(name, ATTRIBUTES_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pIdenTokenParse->state = AWAITING_ROOT_ELEMENT_END; + } + else + { + DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-IdenTokenEndElementHandler- Un-expected state = %d\n", pIdenTokenParse->state); + XML_StopParser(pIdenTokenParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-IdenTokenEndElementHandler- 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; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + + DbgTrace(2, "-AddReference- Start\n", 0); + + // Increment the reference count on the object + PlatAcquireMutex(g_idenTokenIfMutex); + pIdenTokenIfInstance->refCount ++; + refCount = pIdenTokenIfInstance->refCount; + PlatReleaseMutex(g_idenTokenIfMutex); + + 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; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + + DbgTrace(2, "-ReleaseReference- Start\n", 0); + + // Decrement the reference count on the object and determine if it needs to + // be released. + PlatAcquireMutex(g_idenTokenIfMutex); + pIdenTokenIfInstance->refCount --; + if (pIdenTokenIfInstance->refCount == 0) + { + // The object needs to be released, forget about it. + freeObj = true; + g_numIdenTokenIfObjs --; + } + PlatReleaseMutex(g_idenTokenIfMutex); + + // Free object if necessary + if (freeObj) + { + FreeIdenTokenIfInstance(pIdenTokenIfInstance); + } + + 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; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + + DbgTrace(2, "-GetIdentityId- Start\n", 0); + + // Check the input parameters + if (pIfInstance == NULL + || pIdentIdLen == NULL + || (pIdentIdBuf == NULL && *pIdentIdLen != 0)) + { + DbgTrace(0, "-GetIdentityId- Invalid parameter\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Determine if the caller's buffer is large enough + if (*pIdentIdLen >= pIdenTokenIfInstance->identIdLen) + { + // Return the data to the caller + memcpy(pIdentIdBuf, pIdenTokenIfInstance->pIdentId, pIdenTokenIfInstance->identIdLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + + // Return the lenght of the id + *pIdentIdLen = pIdenTokenIfInstance->identIdLen; + +exit: + + 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; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + + DbgTrace(2, "-GetSourceName- Start\n", 0); + + // Check the input parameters + if (pIfInstance == NULL + || pSourceNameLen == NULL + || (pSourceNameBuf == NULL && *pSourceNameLen != 0)) + { + DbgTrace(0, "-GetSourceName- Invalid parameter\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Determine if the caller's buffer is large enough + if (*pSourceNameLen >= pIdenTokenIfInstance->identSourceNameLen) + { + // Return the data to the caller + memcpy(pSourceNameBuf, pIdenTokenIfInstance->pIdentSourceName, pIdenTokenIfInstance->identSourceNameLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + + // Return the lenght of the source name + *pSourceNameLen = pIdenTokenIfInstance->identSourceNameLen; + +exit: + + 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; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + + DbgTrace(2, "-GetSourceUrl- Start\n", 0); + + // Check the input parameters + if (pIfInstance == NULL + || pSourceUrlLen == NULL + || (pSourceUrlBuf == NULL && *pSourceUrlLen != 0)) + { + DbgTrace(0, "-GetSourceUrl- Invalid parameter\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Determine if the caller's buffer is large enough + if (*pSourceUrlLen >= pIdenTokenIfInstance->identSourceUrlLen) + { + // Return the data to the caller + memcpy(pSourceUrlBuf, pIdenTokenIfInstance->pIdentSourceUrl, pIdenTokenIfInstance->identSourceUrlLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + + // Return the lenght of the source url + *pSourceUrlLen = pIdenTokenIfInstance->identSourceUrlLen; + +exit: + + 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. 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. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf); + LIST_ENTRY *pListEntry; + int i; + Attribute *pAttribute; + + DbgTrace(2, "-AttributeEnumerate- Start\n", 0); + + // Check the input parameters + if (pIfInstance == NULL + || pEnumHandle == NULL + || pAttribNameLen == NULL + || pAttribValueLen == NULL + || (pAttribNameBuf == NULL && *pAttribNameLen != 0) + || (pAttribValueBuf == NULL && *pAttribValueLen != 0)) + { + DbgTrace(0, "-AttributeEnumerate- Invalid parameter\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Find the appropriate attribute based on the enum handle which is used as + // an index. + i = 0; + pAttribute = NULL; + pListEntry = pIdenTokenIfInstance->attributeListHead.Flink; + while (pListEntry != &pIdenTokenIfInstance->attributeListHead) + { + // Is this the attribute needed + if (i == *pEnumHandle) + { + // This is the attribute needed + pAttribute = CONTAINING_RECORD(pListEntry, Attribute, listEntry); + break; + } + else + { + // No, try the next one. + pListEntry = pListEntry->Flink; + i++; + } + } + + // Check if we found an attribute for the indicated enum handle + if (pAttribute) + { + // Try to return the attribute name + if (*pAttribNameLen >= pAttribute->attribNameLen) + { + // Return the attribute name + memcpy(pAttribNameBuf, pAttribute->pAttribName, pAttribute->attribNameLen); + + // Now, try to return the attribute value + if (*pAttribValueLen >= pAttribute->attribValueLen) + { + // Return the attribute value + memcpy(pAttribValueBuf, pAttribute->pAttribValue, pAttribute->attribValueLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + + // Advance the enum handle + *pEnumHandle = *pEnumHandle + 1; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + + // Return the attribute lengths + *pAttribNameLen = pAttribute->attribNameLen; + *pAttribValueLen = pAttribute->attribValueLen; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_NO_MORE_ENTRIES); + } + +exit: + + DbgTrace(2, "-AttributeEnumerate- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +GetIdenTokenInterface( + IN const char *pTokenBuf, + IN const int tokenLen, + INOUT IdenTokenIf **ppIdenTokenIf) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Get principal interface instanced for the identity associated +// with specified identity token. +// +// L2 +//=======================================================================-- +{ + IdenTokenIfInstance *pIdenTokenIfInstance; + CasaStatus retStatus; + + DbgTrace(2, "-GetIdenTokenInterface- Start\n", 0); + + // Create a IdenTokenIfInstance object for it. + pIdenTokenIfInstance = malloc(sizeof(*pIdenTokenIfInstance)); + if (pIdenTokenIfInstance) + { + XML_Parser p; + IdenTokenParse idenTokenParse = {0}; + + /* + * CASA identity tokens have the following format: + * + * + * + * identity id + * identity data source name + * identity data source url + * target service name + * target host name + * + * attribute value + * attribute value + * ... + * + * + * + */ + + // Initialize the IdentTokenIfInstance object and set it in the + // idenTokenParse object. + memset(pIdenTokenIfInstance, 0, sizeof(*pIdenTokenIfInstance)); + InitializeListHead(&pIdenTokenIfInstance->attributeListHead); + pIdenTokenIfInstance->idenTokenIf.addReference = AddReference; + pIdenTokenIfInstance->idenTokenIf.releaseReference = ReleaseReference; + pIdenTokenIfInstance->idenTokenIf.getIdentityId = GetIdentityId; + pIdenTokenIfInstance->idenTokenIf.getSourceName = GetSourceName; + pIdenTokenIfInstance->idenTokenIf.getSourceUrl = GetSourceUrl; + pIdenTokenIfInstance->idenTokenIf.attributeEnumerate = AttributeEnumerate; + + idenTokenParse.pIdenTokenIfInstance = pIdenTokenIfInstance; + + // Create parser + p = XML_ParserCreate(NULL); + if (p) + { + // Keep track of the parser in our parse object + idenTokenParse.p = p; + + // Initialize the status within the parse object + idenTokenParse.status = CASA_STATUS_SUCCESS; + + // Set the start and end element handlers + XML_SetElementHandler(p, + IdenTokenStartElementHandler, + IdenTokenEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, IdenTokenCharDataHandler); + + + // Set our user data + XML_SetUserData(p, &idenTokenParse); + + // Parse the document + if (XML_Parse(p, pTokenBuf, tokenLen, 1) == XML_STATUS_OK) + { + // Verify that the parse operation completed successfully + if (idenTokenParse.state == DONE_PARSING) + { + // The parse operation succeded. + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-GetIdenTokenInterface- Parse operation did not complete\n", 0); + + // Check if a status has been recorded + if (idenTokenParse.status != CASA_STATUS_SUCCESS) + { + retStatus = idenTokenParse.status; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + } + } + else + { + DbgTrace(0, "-GetIdenTokenInterface- Parse error %d\n", XML_GetErrorCode(p)); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + + // Free the parser + XML_ParserFree(p); + } + else + { + DbgTrace(0, "-CreateAuthToken- Parser creation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + + // Return the Identity Token Interface to the caller if successful + if (CASA_SUCCESS(retStatus)) + { + // Return the IdenTokenIf associated with the instance data after + // incrementing its reference count. + pIdenTokenIfInstance->refCount ++; + *ppIdenTokenIf = &pIdenTokenIfInstance->idenTokenIf; + + // Bump up our interface instance count + PlatAcquireMutex(g_idenTokenIfMutex); + g_numIdenTokenIfObjs ++; + PlatReleaseMutex(g_idenTokenIfMutex); + } + else + { + FreeIdenTokenIfInstance(pIdenTokenIfInstance); + } + } + else + { + DbgTrace(0, "-GetIdenTokenInterface- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(2, "-GetIdenTokenInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +IdenTokenIfInit(void) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Initializes the identity token interface complex. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + + DbgTrace(1, "-IdenTokenIfInit- Start\n", 0); + + // Allocate mutex + if ((g_idenTokenIfMutex = PlatAllocMutex()) != NULL) + retStatus = CASA_STATUS_SUCCESS; + else + retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + + DbgTrace(1, "-IdenTokenIfInit- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +IdenTokenIfUninit(void) +// +// Arguments: +// +// Returns: +// Casa Status +// +// Description: +// Uninitializes the configuration interface complex. +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "-IdenTokenIfUninit- Start\n", 0); + + // Free mutex if necessary + if (g_idenTokenIfMutex) + { + PlatDestroyMutex(g_idenTokenIfMutex); + g_idenTokenIfMutex = NULL; + } + + DbgTrace(1, "-IdenTokenIfUninit- End\n", 0); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/identokenprovider.c b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/identokenprovider.c new file mode 100644 index 00000000..072f6372 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/identokenprovider.c @@ -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 + * + ***********************************************************************/ + +//===[ 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; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/internal.h b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/internal.h new file mode 100644 index 00000000..13b200c9 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/internal.h @@ -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 + * + ***********************************************************************/ + +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +//===[ Include files ]===================================================== + +#include "platform.h" +#include +#include +#include +#include +#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_ + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/CasaIdentityToken.conf b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/CasaIdentityToken.conf new file mode 100644 index 00000000..656bd9d6 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/CasaIdentityToken.conf @@ -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 + + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/CasaIdentityToken_lib64.conf b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/CasaIdentityToken_lib64.conf new file mode 100644 index 00000000..b377307b --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/CasaIdentityToken_lib64.conf @@ -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 + + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/Makefile.am b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/Makefile.am new file mode 100644 index 00000000..1124f371 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.c b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.c new file mode 100644 index 00000000..75bafc2b --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.c @@ -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 + * + ***********************************************************************/ + +//===[ 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); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.h b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.h new file mode 100644 index 00000000..cc32cd17 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/linux/platform.h @@ -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 + * + ***********************************************************************/ + +#define _GNU_SOURCE + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//===[ 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 ]=============================================== + +//========================================================================= + diff --git a/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/util.c b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/util.c new file mode 100644 index 00000000..4e887979 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/util.c @@ -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 + * + ***********************************************************************/ + +//===[ 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; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/server/AuthTokenValidate/iden_token_provider_if.h b/CASA-auth-token/server/AuthTokenValidate/iden_token_provider_if.h new file mode 100644 index 00000000..9f9a6339 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/iden_token_provider_if.h @@ -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 + * + ***********************************************************************/ + +#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_ + diff --git a/CASA-auth-token/server/AuthTokenValidate/identoken.c b/CASA-auth-token/server/AuthTokenValidate/identoken.c new file mode 100644 index 00000000..b4888c3c --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/identoken.c @@ -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 + * + ***********************************************************************/ + +//===[ 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); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/server/AuthTokenValidate/internal.h b/CASA-auth-token/server/AuthTokenValidate/internal.h new file mode 100644 index 00000000..7cabd823 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/internal.h @@ -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 + * + ***********************************************************************/ + +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +//===[ Include files ]===================================================== + +#include "platform.h" +#include +#include +#include +#include +#include +#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_ + diff --git a/CASA-auth-token/server/AuthTokenValidate/linux/Makefile.am b/CASA-auth-token/server/AuthTokenValidate/linux/Makefile.am new file mode 100644 index 00000000..7a4f57ed --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/linux/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/AuthTokenValidate/linux/platform.c b/CASA-auth-token/server/AuthTokenValidate/linux/platform.c new file mode 100644 index 00000000..ec77a091 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/linux/platform.c @@ -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 + * + ***********************************************************************/ + +//===[ 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; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/server/AuthTokenValidate/linux/platform.h b/CASA-auth-token/server/AuthTokenValidate/linux/platform.h new file mode 100644 index 00000000..561ba7eb --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/linux/platform.h @@ -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 + * + ***********************************************************************/ + +#define _GNU_SOURCE + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//===[ 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 ]=============================================== + + + +//========================================================================= + diff --git a/CASA-auth-token/server/AuthTokenValidate/principal.c b/CASA-auth-token/server/AuthTokenValidate/principal.c new file mode 100644 index 00000000..e4361731 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/principal.c @@ -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 + * + ***********************************************************************/ + + +//===[ 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); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/server/AuthTokenValidate/util.c b/CASA-auth-token/server/AuthTokenValidate/util.c new file mode 100644 index 00000000..bf6a48b6 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/util.c @@ -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 + * + ***********************************************************************/ + +//===[ 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; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/server/AuthTokenValidate/validate.c b/CASA-auth-token/server/AuthTokenValidate/validate.c new file mode 100644 index 00000000..a40f4c08 --- /dev/null +++ b/CASA-auth-token/server/AuthTokenValidate/validate.c @@ -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 + * + ***********************************************************************/ + +//===[ 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)(); +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/CASA-auth-token/server/COPYING b/CASA-auth-token/server/COPYING new file mode 100644 index 00000000..b0ab9a23 --- /dev/null +++ b/CASA-auth-token/server/COPYING @@ -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 + diff --git a/CASA-auth-token/server/ChangeLog b/CASA-auth-token/server/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/CASA-auth-token/server/Makefile.am b/CASA-auth-token/server/Makefile.am new file mode 100644 index 00000000..b5104888 --- /dev/null +++ b/CASA-auth-token/server/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/NEWS b/CASA-auth-token/server/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/CASA-auth-token/server/PamSupport/Makefile.am b/CASA-auth-token/server/PamSupport/Makefile.am new file mode 100644 index 00000000..a9fff5ba --- /dev/null +++ b/CASA-auth-token/server/PamSupport/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/PamSupport/README b/CASA-auth-token/server/PamSupport/README new file mode 100644 index 00000000..1b8df1dd --- /dev/null +++ b/CASA-auth-token/server/PamSupport/README @@ -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 + * + ***********************************************************************/ +/*********************************************************************** + * + * 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. + + + + + + + + + + diff --git a/CASA-auth-token/server/PamSupport/TODO b/CASA-auth-token/server/PamSupport/TODO new file mode 100644 index 00000000..90fb8aeb --- /dev/null +++ b/CASA-auth-token/server/PamSupport/TODO @@ -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. diff --git a/CASA-auth-token/server/PamSupport/linux/Makefile.am b/CASA-auth-token/server/PamSupport/linux/Makefile.am new file mode 100644 index 00000000..3d16b58a --- /dev/null +++ b/CASA-auth-token/server/PamSupport/linux/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/PamSupport/pam_authtoken.c b/CASA-auth-token/server/PamSupport/pam_authtoken.c new file mode 100644 index 00000000..44f2b296 --- /dev/null +++ b/CASA-auth-token/server/PamSupport/pam_authtoken.c @@ -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 + * + ***********************************************************************/ + +#define _GNU_SOURCE + +#include +#include +#include + +#ifndef LINUX +#include +#endif + +#define PAM_SM_AUTH +#define PAM_SM_ACCOUNT +#define PAM_SM_PASSWORD +#define PAM_SM_SESSION + +#include +#include + +#include + +// +// 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 + diff --git a/CASA-auth-token/server/PamSupport/test/README b/CASA-auth-token/server/PamSupport/test/README new file mode 100644 index 00000000..b15463c5 --- /dev/null +++ b/CASA-auth-token/server/PamSupport/test/README @@ -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 + + + + + + + + + + diff --git a/CASA-auth-token/server/PamSupport/test/make.sh b/CASA-auth-token/server/PamSupport/test/make.sh new file mode 100755 index 00000000..04f14272 --- /dev/null +++ b/CASA-auth-token/server/PamSupport/test/make.sh @@ -0,0 +1,2 @@ +#!/bin/bash +gcc -o pamTest test.c -g -DN_PLAT_UNIX -L"../../../lib/Release" -lpam diff --git a/CASA-auth-token/server/PamSupport/test/test.c b/CASA-auth-token/server/PamSupport/test/test.c new file mode 100644 index 00000000..00b05921 --- /dev/null +++ b/CASA-auth-token/server/PamSupport/test/test.c @@ -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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//===[ 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() --*/ + diff --git a/CASA-auth-token/server/PamSupport/test/testservice b/CASA-auth-token/server/PamSupport/test/testservice new file mode 100644 index 00000000..452e1efb --- /dev/null +++ b/CASA-auth-token/server/PamSupport/test/testservice @@ -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 + diff --git a/CASA-auth-token/server/README b/CASA-auth-token/server/README new file mode 100644 index 00000000..48d961e0 --- /dev/null +++ b/CASA-auth-token/server/README @@ -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 + * + ***********************************************************************/ +/*********************************************************************** + * + * 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=/ [--enable-debug] +( 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/ [--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 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. + + + + + + + + diff --git a/CASA-auth-token/server/TODO b/CASA-auth-token/server/TODO new file mode 100644 index 00000000..ca5a4629 --- /dev/null +++ b/CASA-auth-token/server/TODO @@ -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. diff --git a/CASA-auth-token/server/autogen.sh b/CASA-auth-token/server/autogen.sh new file mode 100755 index 00000000..19ad55ec --- /dev/null +++ b/CASA-auth-token/server/autogen.sh @@ -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 diff --git a/CASA-auth-token/server/configure.in b/CASA-auth-token/server/configure.in new file mode 100644 index 00000000..1fdca6a2 --- /dev/null +++ b/CASA-auth-token/server/configure.in @@ -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 +]) + diff --git a/CASA-auth-token/server/include/Makefile.am b/CASA-auth-token/server/include/Makefile.am new file mode 100644 index 00000000..f506f2fe --- /dev/null +++ b/CASA-auth-token/server/include/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/include/casa_c_ipc.h b/CASA-auth-token/server/include/casa_c_ipc.h new file mode 100644 index 00000000..f3982156 --- /dev/null +++ b/CASA-auth-token/server/include/casa_c_ipc.h @@ -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 + * + ***********************************************************************/ + +#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_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/server/include/casa_s_authtoken.h b/CASA-auth-token/server/include/casa_s_authtoken.h new file mode 100644 index 00000000..b0d29954 --- /dev/null +++ b/CASA-auth-token/server/include/casa_s_authtoken.h @@ -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 + * + ***********************************************************************/ + +#ifndef _CASA_S_AUTHTOKEN_H_ +#define _CASA_S_AUTHTOKEN_H_ + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" +{ +#endif + +//===[ Include files ]===================================================== + +#include +#include + +//===[ 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_ + diff --git a/CASA-auth-token/server/include/casa_s_ipc.h b/CASA-auth-token/server/include/casa_s_ipc.h new file mode 100644 index 00000000..c867cae7 --- /dev/null +++ b/CASA-auth-token/server/include/casa_s_ipc.h @@ -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 + * + ***********************************************************************/ + +#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_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/server/include/list_entry.h b/CASA-auth-token/server/include/list_entry.h new file mode 100644 index 00000000..f482b464 --- /dev/null +++ b/CASA-auth-token/server/include/list_entry.h @@ -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 + +//===[ 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_ + + diff --git a/CASA-auth-token/server/package/Makefile.am b/CASA-auth-token/server/package/Makefile.am new file mode 100644 index 00000000..79732539 --- /dev/null +++ b/CASA-auth-token/server/package/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/package/linux/CASA_auth_token_client.changes b/CASA-auth-token/server/package/linux/CASA_auth_token_client.changes new file mode 100644 index 00000000..8629e98d --- /dev/null +++ b/CASA-auth-token/server/package/linux/CASA_auth_token_client.changes @@ -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. + +------------------------------------------------------------------- + diff --git a/CASA-auth-token/server/package/linux/CASA_auth_token_server.changes b/CASA-auth-token/server/package/linux/CASA_auth_token_server.changes new file mode 100644 index 00000000..8629e98d --- /dev/null +++ b/CASA-auth-token/server/package/linux/CASA_auth_token_server.changes @@ -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. + +------------------------------------------------------------------- + diff --git a/CASA-auth-token/server/package/linux/CASA_auth_token_server.spec.in b/CASA-auth-token/server/package/linux/CASA_auth_token_server.spec.in new file mode 100644 index 00000000..2314fa0a --- /dev/null +++ b/CASA-auth-token/server/package/linux/CASA_auth_token_server.spec.in @@ -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 diff --git a/CASA-auth-token/server/package/linux/Makefile.am b/CASA-auth-token/server/package/linux/Makefile.am new file mode 100644 index 00000000..c80e232e --- /dev/null +++ b/CASA-auth-token/server/package/linux/Makefile.am @@ -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 + diff --git a/CASA-auth-token/server/utilities/IpcLibs/Makefile.am b/CASA-auth-token/server/utilities/IpcLibs/Makefile.am new file mode 100644 index 00000000..a9fff5ba --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/utilities/IpcLibs/README b/CASA-auth-token/server/utilities/IpcLibs/README new file mode 100644 index 00000000..efdcea61 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/README @@ -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 + * + ***********************************************************************/ +/*********************************************************************** + * + * 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. + + + + + + + + + diff --git a/CASA-auth-token/server/utilities/IpcLibs/TODO b/CASA-auth-token/server/utilities/IpcLibs/TODO new file mode 100644 index 00000000..f8074da2 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/TODO @@ -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. + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/Makefile.am b/CASA-auth-token/server/utilities/IpcLibs/linux/Makefile.am new file mode 100644 index 00000000..b45d9d96 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/client/Makefile.am b/CASA-auth-token/server/utilities/IpcLibs/linux/client/Makefile.am new file mode 100644 index 00000000..53c41a45 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/client/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/client/cchannel.cpp b/CASA-auth-token/server/utilities/IpcLibs/linux/client/cchannel.cpp new file mode 100644 index 00000000..bd7be4ea --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/client/cchannel.cpp @@ -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 + * + ***********************************************************************/ + + +//===[ 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 *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() --*/ + + +//========================================================================= +//========================================================================= + + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/client/cchannel.h b/CASA-auth-token/server/utilities/IpcLibs/linux/client/cchannel.h new file mode 100644 index 00000000..093c1e49 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/client/cchannel.h @@ -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 + * + ***********************************************************************/ + +#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 RCMap; + typedef RCMap::iterator RCMapIter; + typedef pair RCIterBoolPair; + RCMap m_rcMap; + + // + // Service connection thread procedure + // + // Parameters: + // pSmartCChannel (input) - + // Pointer to SmartPtr object. + // + // Abstract: Thread in charge of servicing channel connection. + // + // Returns: Nothing. + // + static void* connectionThread(SmartPtr *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 SmartCChannel; + + +//===[ Function prototypes ]=============================================== + + +#endif // _CCHANNEL_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/client/client.cpp b/CASA-auth-token/server/utilities/IpcLibs/linux/client/client.cpp new file mode 100644 index 00000000..f2c977cf --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/client/client.cpp @@ -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 + * + ***********************************************************************/ + + +//===[ 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*> REPMap; +typedef REPMap::iterator REPMapIter; +typedef pair 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(); +} + + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/client/clientreq.cpp b/CASA-auth-token/server/utilities/IpcLibs/linux/client/clientreq.cpp new file mode 100644 index 00000000..985a6ad1 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/client/clientreq.cpp @@ -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 + * + ***********************************************************************/ + + +//===[ 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() --*/ + + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/client/clientreq.h b/CASA-auth-token/server/utilities/IpcLibs/linux/client/clientreq.h new file mode 100644 index 00000000..d707a9bb --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/client/clientreq.h @@ -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 + * + ***********************************************************************/ + + +#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_ + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/client/remoteendpoint.cpp b/CASA-auth-token/server/utilities/IpcLibs/linux/client/remoteendpoint.cpp new file mode 100644 index 00000000..49919dfa --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/client/remoteendpoint.cpp @@ -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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "ipcint.h" +#include "cchannel.h" +#include "clientreq.h" +#include "remoteendpoint.h" +#include // 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() --*/ + + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/client/remoteendpoint.h b/CASA-auth-token/server/utilities/IpcLibs/linux/client/remoteendpoint.h new file mode 100644 index 00000000..f7bd6a4f --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/client/remoteendpoint.h @@ -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 + * + ***********************************************************************/ + + +#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 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 SmartRemoteEndPoint; + + +//===[ Function prototypes ]=============================================== + + +#endif // _REMOTEENDPOINT_ + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/client/test/makeClient.sh b/CASA-auth-token/server/utilities/IpcLibs/linux/client/test/makeClient.sh new file mode 100755 index 00000000..f810ece5 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/client/test/makeClient.sh @@ -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 + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/client/test/testClient.c b/CASA-auth-token/server/utilities/IpcLibs/linux/client/test/testClient.c new file mode 100644 index 00000000..20be5968 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/client/test/testClient.c @@ -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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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() --*/ + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/common/Makefile.am b/CASA-auth-token/server/utilities/IpcLibs/linux/common/Makefile.am new file mode 100644 index 00000000..fada063a --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/common/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/common/channelproto.cpp b/CASA-auth-token/server/utilities/IpcLibs/linux/common/channelproto.cpp new file mode 100644 index 00000000..c20fb353 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/common/channelproto.cpp @@ -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 + * + ***********************************************************************/ + + +//===[ 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() --*/ + + +//========================================================================= +//========================================================================= + + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/common/channelproto.h b/CASA-auth-token/server/utilities/IpcLibs/linux/common/channelproto.h new file mode 100644 index 00000000..669a22ac --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/common/channelproto.h @@ -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 + * + ***********************************************************************/ + +#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_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/common/ipcint.h b/CASA-auth-token/server/utilities/IpcLibs/linux/common/ipcint.h new file mode 100644 index 00000000..3553c18e --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/common/ipcint.h @@ -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 + * + ***********************************************************************/ + +#ifndef _IPCINT_ +#define _IPCINT_ + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +using namespace std; + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // Ensure that NDEBUG is defined for release builds! +#include +} + +//===[ 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_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/common/smartptr.h b/CASA-auth-token/server/utilities/IpcLibs/linux/common/smartptr.h new file mode 100644 index 00000000..1cd05280 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/common/smartptr.h @@ -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 SmartPtr +{ + //--------------------------------------------------------------------------- + // Public interface + // + public: + + SmartPtr(); + SmartPtr(T* ptr); + SmartPtr(const SmartPtr& ref); + + virtual ~SmartPtr(); + + operator bool (void) const; + bool operator! (void) const; + bool operator== (SmartPtr& ref) const; + bool operator!= (SmartPtr& ref) const; + + SmartPtr& operator= (const SmartPtr& ref); + SmartPtr& 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 +inline SmartPtr::SmartPtr() : + m_Ptr(0) +{ +} // End of SmartPtr::SmartPtr() + + +template +inline SmartPtr::SmartPtr(T* ptr) : + m_Ptr(0) +{ + resetPtr(ptr); + +} // End of SmartPtr::SmartPtr() + + +template +inline SmartPtr::SmartPtr(const SmartPtr& ref) : + m_Ptr(0) +{ + resetPtr(ref.m_Ptr); + +} // End of SmartPtr::SmartPtr() + + +template +inline SmartPtr::~SmartPtr() +{ + deleteObject(); + +} // End of SmartPtr::~SmartPtr() + + +template +inline SmartPtr::operator bool (void) const +{ + return m_Ptr != 0; + +} // End of SmartPtr::operator bool() + + +template +inline bool SmartPtr::operator! (void) const +{ + return m_Ptr == 0; + +} // End of SmartPtr::operator!() + + +template +inline bool SmartPtr::operator== (SmartPtr& ref) const +{ + return m_Ptr == ref.m_Ptr; + +} // End of SmartPtr::operator==() + + +template +inline bool SmartPtr::operator!= (SmartPtr& ref) const +{ + return m_Ptr != ref.m_Ptr; + +} // End of SmartPtr::operator==() + + +template +inline SmartPtr& SmartPtr::operator= (const SmartPtr& ref) +{ + resetPtr(ref.m_Ptr); + return *this; + +} // End of SmartPtr::operator=() + + +template +inline SmartPtr& SmartPtr::operator= (T* ptr) +{ + resetPtr(ptr); + return *this; + +} // End of SmartPtr::operator=() + + +template +inline T& SmartPtr::operator* (void) const +{ + return *m_Ptr; + +} // End of SmartPtr::operator*() + + +template +inline T* SmartPtr::operator-> (void) const +{ + return m_Ptr; + +} // End of SmartPtr::operator->() + + +template +inline SmartPtr::operator T* (void) const +{ + return m_Ptr; + +} // End of SmartPtr::operator T*() + + +template +inline void SmartPtr::deleteObject(void) +{ + if (m_Ptr && m_Ptr->DecRefCount()) + { + delete m_Ptr; + m_Ptr = 0; + } + +} // End of SmartPtr::deleteObject() + + +template +inline void SmartPtr::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 + +/******************************************************************************/ +/******************************************************************************/ + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/server/Makefile.am b/CASA-auth-token/server/utilities/IpcLibs/linux/server/Makefile.am new file mode 100644 index 00000000..5119d0b0 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/server/Makefile.am @@ -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 +# +####################################################################### + +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 + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/server/schannel.cpp b/CASA-auth-token/server/utilities/IpcLibs/linux/server/schannel.cpp new file mode 100644 index 00000000..8dd49c34 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/server/schannel.cpp @@ -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 + * + ***********************************************************************/ + + +//===[ 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 *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() --*/ + + +//========================================================================= +//========================================================================= + + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/server/schannel.h b/CASA-auth-token/server/utilities/IpcLibs/linux/server/schannel.h new file mode 100644 index 00000000..963256d4 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/server/schannel.h @@ -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 + * + ***********************************************************************/ + +#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 RSMap; + typedef RSMap::iterator RSMapIter; + typedef pair RSIterBoolPair; + RSMap m_rsMap; + + // + // Service connection thread procedure + // + // Parameters: + // pSmartSChannel (input) - + // Pointer to SmartPtr object. + // + // Abstract: Thread in charge of servicing channel connection. + // + // Returns: Nothing. + // + static void* connectionThread(SmartPtr *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 SmartSChannel; + + +//===[ Function prototypes ]=============================================== + + +#endif // _SCHANNEL_ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/server/server.cpp b/CASA-auth-token/server/utilities/IpcLibs/linux/server/server.cpp new file mode 100644 index 00000000..f562ccd9 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/server/server.cpp @@ -0,0 +1,1354 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include "ipcint.h" + +extern "C" { +#include "casa_s_ipc.h" +} + +#include "schannel.h" +#include "serverthread.h" +#include "serverreq.h" + + +//===[ Type definitions ]================================================== + +#define MAX_FILE_PATH_LEN 1024 + +// +// 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 ]=============================================== + + +extern unsigned long numServerReqObjects; +extern unsigned long numSChannelObjects; + + +//===[ Global variables ]================================================== + +// Debug variables +int DebugLevel = 0; +bool UseSyslog = false; + +// Application Name for logging purposes +char unInitialized[] = "Uninitialized"; +char *pAppName = unInitialized; + +// Indicators +bool svcInitialized = false; +bool svcStarted = false; +bool serverAddressSet = false; + +// Listen Port Number +bool use_AF_INET; +bool use_PF_UNIX; +unsigned short int listenPortNumber = 0; +char listenSocketFile[MAX_FILE_PATH_LEN]; + +// Listening Socket +int listenSocket = INVALID_SOCKET; + +// Operating parameters +bool acceptingConnections = true; +bool terminating = false; + +// SChannel list +list sChannelList; +pthread_mutex_t serverMutex; + +// Mutex for interlocked operations +pthread_mutex_t interlockedMutex; + +// +// Active 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. Note, this id is associated with +// a request when ProcessRequest() is called and it does +// not have anything to do with the requests rpc id. +// +typedef map RSMap; +typedef RSMap::iterator RSMapIter; +typedef pair RSIterBoolPair; +RSMap rsMap; +int numActiveRequests = 0; + +// +// Next request id (Can not be zero) +// +int32_t nextReqId = 1; + +// +// Pending ServerRequests List and count - Server requests are staged on this lists until +// they become active. +// +list pendingServerReqList; +int numPendingRequests = 0; + +// ServerThreads operating parameters +list waitingServerThreadList; +int waitingServerThreads = 0; + + +//++======================================================================= +int +ServiceRequest( + ServerReq *pServerReq) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + + DbgTrace(1, "ServiceRequest- Start\n", 0); + + // Obtain server mutex + pthread_mutex_lock(&serverMutex); + + // Do not process if trying to terminate + if (!terminating) + { + try { + + // Insert the request into the pending server request list + pendingServerReqList.push_back(pServerReq); + numPendingRequests ++; + + // Check if there is a thread that can be awaken to process the request + if (waitingServerThreads) + { + // There are waiting ServerThreads, remove one from the list + // and reduce the waitingServerThreads count. + list::iterator iter = waitingServerThreadList.begin(); + ServerThread *pServerThread = *iter; + waitingServerThreadList.erase(iter); + waitingServerThreads --; + + // Wake up the server thread + pServerThread->awaken(); + } + + // Success + retStatus = 0; + } + catch (...) { + DbgTrace(0, "ServiceRequest- Exception caught\n", 0); + } + } + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + + DbgTrace(1, "ServiceRequest- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- ServiceRequest() --*/ + + +//++======================================================================= +void +AbortPendingRequests(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "AbortPendingRequests- Start\n", 0); + + // Obtain server mutex + pthread_mutex_lock(&serverMutex); + + // Abort and delete all of the ServerReq in the pendingServerReqList + while (numPendingRequests) + { + list::iterator iter = pendingServerReqList.begin(); + ServerReq *pServerReq = *iter; + pendingServerReqList.erase(iter); + numPendingRequests --; + + pServerReq->abort(); + delete pServerReq; + } + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + + DbgTrace(1, "AbortPendingRequests- End\n", 0); + +} /*-- AbortPendingRequests() --*/ + + +//++======================================================================= +void +AwakenSuspendedServerThreads(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "AwakenSuspendedServerThreads- Start\n", 0); + + // Obtain server mutex + pthread_mutex_lock(&serverMutex); + + // Awaken all of the ServerThreads in the waitingServerThreadsList + while (waitingServerThreads) + { + list::iterator iter = waitingServerThreadList.begin(); + ServerThread *pServerThread = *iter; + waitingServerThreadList.erase(iter); + waitingServerThreads --; + + // Wake up the server thread + pServerThread->awaken(); + } + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + + DbgTrace(1, "AwakenSuspendedServerThreads- End\n", 0); + +} /*-- AwakenSuspendedServerThreads() --*/ + + +//++======================================================================= +void +RemoveFromSChannelList( + SChannel *pSChannel) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + list::iterator iter; + bool objectRemoved = false; + + DbgTrace(1, "RemoveFromSChannelList- Start, Obj = %08X\n", pSChannel); + + // Obtain server mutex + pthread_mutex_lock(&serverMutex); + + // Find the object in the list + if (!sChannelList.empty()) + { + iter = sChannelList.begin(); + while (iter != sChannelList.end()) + { + if (*iter == pSChannel) + { + // Object found, remove it from the list. + sChannelList.erase(iter); + + // Remember that we removed the object + objectRemoved = true; + break; + } + + // Proceed to the next item + iter ++; + } + } + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + + // Check if the object was removed + if (objectRemoved == false) + { + DbgTrace(0, "RemoveFromSChannelList- Error, did not find object in list\n", 0); + } + + DbgTrace(1, "RemoveFromSChannelList- End\n", 0); + +} /*-- RemoveFromSChannelList() --*/ + + +//++======================================================================= +void +ShutdownSChannels(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + list::iterator iter; + SChannel *pSChannel; + struct timespec waitTime = {0}; + + DbgTrace(1, "ShutdownSChannels- Start\n", 0); + + // Obtain server mutex + pthread_mutex_lock(&serverMutex); + + // Close all of the SChannels in the SChannelList + if (!sChannelList.empty()) + { + iter = sChannelList.begin(); + while (iter != sChannelList.end()) + { + // Found SChannel in the idle list, close it. + (*iter)->closeChannel(); + + // Move on to the next item in the list + iter ++; + } + } + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + + // Loop until all SChannels are gone + while (numSChannelObjects != 0) + { + // Wait for sometime + waitTime.tv_sec = 1; // One second + nanosleep(&waitTime, NULL); + } + + DbgTrace(1, "ShutdownSChannels- End\n", 0); + +} /*-- ShutdownSChannels() --*/ + + +//++======================================================================= +int +OpenSocket(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int openedSocket; + + // Open a domain socket if a listen port number has not + // been configured else open a Tcp socket. + if (use_PF_UNIX) + openedSocket = socket(PF_UNIX, SOCK_STREAM, 0); + else + openedSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + return openedSocket; + +} /*-- OpenSocket() --*/ + + +//++======================================================================= +int +BindSocket(int socketToBind) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int retStatus; + + // Bind domain socket if a listen port number has not + // been configured else open a Tcp socket. + if (use_PF_UNIX) + { + struct sockaddr_un listenAddr; + + // Set the file creation mask to 000 + mode_t prevMask = umask(000); + + // Remove pre-existing socket + unlink(listenSocketFile); + + // Setup the address that the daemon will use to listen + // for connections. + listenAddr.sun_family = AF_UNIX; + strcpy(listenAddr.sun_path, listenSocketFile); + + // Perform the bind operation + retStatus = bind(socketToBind, + (const sockaddr*) &listenAddr, + sizeof(listenAddr.sun_family) + strlen(listenAddr.sun_path)); + + // Return the file creation mask to its previous value + umask(prevMask); + } + else + { + struct sockaddr_in listenAddr = {0}; + int on = 1; + + // Setup the address that the daemon will use to listen + // for connections. + listenAddr.sin_family = AF_INET; + listenAddr.sin_addr.s_addr = htonl(INADDR_ANY); + listenAddr.sin_port = htons(listenPortNumber); + + // Set the SO_REUSEADDR option on the socket to avoid + // problems in case of a re-start. + setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + + // Perform the bind operation + retStatus = bind(socketToBind, + (const sockaddr*) &listenAddr, + sizeof(struct sockaddr_in)); + } + + return retStatus; + +} /*-- BindSocket() --*/ + + +//++======================================================================= +int +AcceptConnection(int acceptPendingSocket) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int connectionSocket; + socklen_t remoteAddrLen; + + // Use the appropriate address structure when Accepting connection + if (use_PF_UNIX) + { + struct sockaddr_un remoteAddr; + remoteAddrLen = sizeof(remoteAddr); + + // Perform the accept operation + connectionSocket = accept(acceptPendingSocket, + (struct sockaddr*) &remoteAddr, + &remoteAddrLen); + } + else + { + struct sockaddr_in remoteAddr; + remoteAddrLen = sizeof(remoteAddr); + + // Perform the accept operation + connectionSocket = accept(acceptPendingSocket, + (struct sockaddr*) &remoteAddr, + &remoteAddrLen); + } + + return connectionSocket; + +} /*-- AcceptConnection() --*/ + + +//++======================================================================= +void +ServiceConnections(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int connSocket; + SChannel *pSChannel; + bool sChannelAddedToList = false; + + DbgTrace(1, "ServiceConnections- Start\n", 0); + + // Open listening Tcp socket + listenSocket = OpenSocket(); + if (listenSocket != INVALID_SOCKET) + { + // Bind the socket + if (!BindSocket(listenSocket)) + { + // Socket has been bound to our listen address, now set + // the socket in listen mode. + if (listen(listenSocket, SOMAXCONN) != SOCKET_ERROR) + { + // The socket is now in listen mode, start accepting connections. + while (acceptingConnections) + { + pSChannel = NULL; + connSocket = AcceptConnection(listenSocket); + if (connSocket != INVALID_SOCKET) + { + // We received a new connection + // + // Obtain server mutex + pthread_mutex_lock(&serverMutex); + + // Create a SChannel object to service the connection + try { + + pSChannel = new SChannel(connSocket); + + // Associate a smart pointer with the channel to make sure + // that it does not go away prematurely while we execute + // SChannel::init(), also, this will allow the object to + // get cleaned up if its initialization fails. + SmartSChannel smartSChannel = pSChannel; + + // SChannel created, insert it into the SChannel list. + sChannelList.push_back(pSChannel); + sChannelAddedToList = true; + + // Initialize the SChannel + if (pSChannel->init()) + { + DbgTrace(0, "ServiceConnections- SChannel intialization failed\n", 0); + + // Remove the SChannel object from the SChannel list + sChannelList.pop_back(); + sChannelAddedToList = false; + } + } + catch (...) { + + DbgTrace(0, "ServiceConnections- Exception caught\n", 0); + + // Free necessary resources + if (pSChannel) + { + if (sChannelAddedToList) + sChannelList.pop_back(); + delete pSChannel; + } + else + closesocket(connSocket); + } + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + } + else + { + // Check if accept failed because we got interrupted + if (errno == EINTR) + { + // We got interrupted during the accept, try again. + continue; + } + else + { + // This could be because the listen socket got closed. + DbgTrace(1, "ServiceConnections- Accept failed, error = %d\n", errno); + + // Break out of the accept loop if the socket indeed got closed + if (listenSocket == INVALID_SOCKET) + break; + } + } + } + } + else + { + DbgTrace(0, "ServiceConnections- Listen failed, error = %d\n", errno); + } + } + else + { + DbgTrace(0, "ServiceConnections- Unable to bind socket, error = %d\n", errno); + } + + // Close listening socket if necessary + if (listenSocket != INVALID_SOCKET) + closesocket(listenSocket); + } + else + { + DbgTrace(0, "ServiceConnections- Unable to open socket, error = %d\n", errno); + } + + DbgTrace(1, "ServiceConnections- End\n", 0); + +} /*-- ServiceConnections() --*/ + + +//++======================================================================= +void* ServiceConnectionsThread(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "ServiceConnectionsThread- Start\n", 0); + + // Set the thread in the detached state so that it is cleaned up when it exits + pthread_detach(pthread_self()); + + // Service connections until no longer necessary + ServiceConnections(); + + // Clean up + ShutdownSChannels(); + + DbgTrace(1, "ServiceConnectionsThread- End\n", 0); + + // Exit + pthread_exit(NULL); + + return 0; // never-reached! + +} /*-- ServiceConnectionsThread() --*/ + + +//++======================================================================= +extern "C" +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. +// +// L2 +//=======================================================================-- +{ + int32_t requestId = 0; + + DbgTrace(1, "IpcServerGetRequest- Start\n", 0); + + // Make sure that the service has been started + if (!svcStarted) + { + DbgTrace(0, "IpcServerGetRequest- Service has not been started\n", 0); + goto exit; + } + + try { + + // Instantiate ServerThread object + ServerThread serverThread; + + // Obtain server mutex + pthread_mutex_lock(&serverMutex); + + // Try to find a request to process + while (!terminating) + { + // Make sure that this is initialized to zero + requestId = 0; + + // Check if there is a request for us to process + if (numPendingRequests) + { + // Obtain pending request and place it in the active map + list::iterator iter = pendingServerReqList.begin(); + ServerReq *pServerReq = *iter; + pendingServerReqList.erase(iter); + numPendingRequests --; + + // Assign an id to this request and increment + // the nextReqId. + // + // Protect against zero since it is not valid. + if (nextReqId != 0) + { + requestId = nextReqId; + nextReqId ++; + } + else + { + requestId = 1; + nextReqId = 2; + } + + // Place the request in the active request map + RSIterBoolPair insertResult = rsMap.insert(make_pair(requestId, pServerReq)); + if (!insertResult.second) + { + // Insertion failed + DbgTrace(0, "IpcServerGetRequest- Unable to insert ServerReq into map\n", 0); + + // Abort and free the request + pServerReq->abort(); + delete pServerReq; + + // Try again + continue; + } + else + { + // Increment the number of active requests + numActiveRequests ++; + + // Exit to allow the calling thread to process the request + break; + } + } + else + { + // There is not a request for us to process, place us on the waiting + // server thread list and wait to be awaken. + waitingServerThreadList.push_back(&serverThread); + waitingServerThreads ++; + serverThread.suspend(&serverMutex); + } + } + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + } + catch (...) { + + DbgTrace(1, "IpcServerGetRequest- Exception caught\n", 0); + } + +exit: + + DbgTrace(1, "IpcServerGetRequest- End, requestId = %08X\n", requestId); + + return requestId; + +} /*-- IpcServerGetRequest() --*/ + + +//++======================================================================= +extern "C" +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. +// L2 +//=======================================================================-- +{ + int32_t reqDataLen = 0; + + DbgTrace(1, "IpcServerGetRequestData- Start, requestId = %08X\n", requestId); + + // Make sure that the service has been started + if (svcStarted) + { + // Obtain server mutex + pthread_mutex_lock(&serverMutex); + + // Find request in the active map + RSMapIter iter = rsMap.find(requestId); + if (iter != rsMap.end()) + { + // Request was found in the map, obtain a reference to it. + ServerReq *pServerReq = iter->second; + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + + // Obtain the request data associated with the request + reqDataLen = pServerReq->getReqData(ppReqData); + } + else + { + DbgTrace(0, "IpcServerGetRequestData- Request not found in map\n", 0); + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + } + } + else + { + DbgTrace(0, "IpcServerGetRequestData- Service has not been started\n", 0); + } + + DbgTrace(1, "IpcServerGetRequestData- End, reqDataLen = %08X\n", reqDataLen); + + return reqDataLen; + +} /*-- IpcServerGetRequestData() --*/ + + +//++======================================================================= +extern "C" +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. +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "IpcServerCompleteRequest- Start, requestId = %08X\n", requestId); + + // Make sure that the service has been started + if (svcStarted) + { + // Obtain server mutex + pthread_mutex_lock(&serverMutex); + + // Find request in the active map + RSMapIter iter = rsMap.find(requestId); + if (iter != rsMap.end()) + { + // Request was found in the map, get a reference to it and + // remove it from the map> + ServerReq *pServerReq = iter->second; + rsMap.erase(iter); + numActiveRequests --; + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + + // Coomplete the request and delete it. + pServerReq->complete(pReplyData); + delete pServerReq; + } + else + { + DbgTrace(0, "IpcServerCompleteRequest- Request not found in map\n", 0); + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + } + } + else + { + DbgTrace(0, "IpcServerCompleteRequest- Service has not been started\n", 0); + } + + DbgTrace(1, "IpcServerCompleteRequest- End\n", 0); + +} /*-- IpcServerCompleteRequest() --*/ + + +//++======================================================================= +extern "C" +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: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "IpcServerAbortRequest- Start, requestId = %08X\n", requestId); + + // Make sure that the service has been started + if (svcStarted) + { + // Obtain server mutex + pthread_mutex_lock(&serverMutex); + + // Find request in the active map + RSMapIter iter = rsMap.find(requestId); + if (iter != rsMap.end()) + { + // Request was found in the map, get a reference to it and + // remove it from the map> + ServerReq *pServerReq = iter->second; + rsMap.erase(iter); + numActiveRequests --; + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + + // Coomplete the request and delete it. + pServerReq->abort(); + delete pServerReq; + } + else + { + DbgTrace(0, "IpcServerAbortRequest- Request not found in map\n", 0); + + // Release server mutex + pthread_mutex_unlock(&serverMutex); + } + } + else + { + DbgTrace(0, "IpcServerAbortRequest- Service has not been started\n", 0); + } + + DbgTrace(1, "IpcServerAbortRequest- End\n", 0); + +} /*-- IpcServerAbortRequest() --*/ + + +//++======================================================================= +extern "C" +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. +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + + DbgTrace(1, "IpcServerStart- Start\n", 0); + + // Make sure that the listen address has been set + if (serverAddressSet) + { + // Do not do anything if we have already been started + if (!svcStarted) + { + // Create a threat to service connections + pthread_t thread; + int threadCreateStatus; + threadCreateStatus = pthread_create(&thread, + NULL, + (void*(*)(void*))ServiceConnectionsThread, + (void*)NULL); + if (threadCreateStatus != 0) + { + DbgTrace(0, "IpcServerStart- Unable to create service connections thread, error = %08X\n", threadCreateStatus); + retStatus = -1; + } + else + { + // Success + svcStarted = true; + retStatus = 0; + } + } + } + else + { + DbgTrace(0, "IpcServerStart- Either not initialized or the address has not been set\n", 0); + } + + DbgTrace(1, "IpcServerStart- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- IpcServerStart() --*/ + + +//++======================================================================= +extern "C" +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. +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + + DbgTrace(1, "IpcServerSetUnAddress- Start\n", 0); + + // Verify the input parameters + if (pSocketFileName == NULL + || strlen(pSocketFileName) >= sizeof(listenSocketFile)) + { + DbgTrace(0, "IpcServerSetUnAddress- Invalid input parameter\n", 0); + goto exit; + } + + // Make sure that we have been initialized + if (svcInitialized) + { + // Make sure that the address has not already been set. + if (serverAddressSet == false) + { + // Save a copy of the socket file name + strcpy(listenSocketFile, pSocketFileName); + + // Remember this + serverAddressSet = true; + use_AF_INET = false; + use_PF_UNIX = true; + + // Success + retStatus = 0; + } + else + { + DbgTrace(0, "IpcServerSetUnAddress- Already set\n", 0); + } + } + else + { + DbgTrace(0, "IpcServerSetUnAddress- Service not yet initialized\n", 0); + } + +exit: + + DbgTrace(1, "IpcServerSetUnAddress- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- IpcServerSetUnAddress() --*/ + + +//++======================================================================= +extern "C" +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. +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + + DbgTrace(1, "IpcServerSetInAddress- Start\n", 0); + + // Verify the input parameters + if (listenPort == 0) + { + DbgTrace(0, "IpcServerSetInAddress- Invalid input parameter\n", 0); + goto exit; + } + + // Make sure that we have been initialized + if (svcInitialized) + { + // Make sure that the address has not already been set. + if (serverAddressSet == false) + { + // Save the listen port number + listenPortNumber = listenPort; + + // Remember this + serverAddressSet = true; + use_AF_INET = true; + use_PF_UNIX = false; + + // Success + retStatus = 0; + } + else + { + DbgTrace(0, "IpcServerSetInAddress- Already set\n", 0); + } + } + else + { + DbgTrace(0, "IpcServerSetInAddress- Service not yet initialized\n", 0); + } + +exit: + + DbgTrace(1, "IpcServerSetInAddress- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- IpcServerSetInAddress() --*/ + + +//++======================================================================= +extern "C" +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. +// +// L2 +//=======================================================================-- +{ + int retStatus = -1; + + DbgTrace(1, "IpcServerInit- Start\n", 0); + + // Check input parameters + if (pAppName == NULL) + { + DbgTrace(0, "IpcServerInit- Invalid parameter\n", 0); + goto exit; + } + + // Save a copy of the application name + pAppName = new char[strlen(pName) + 1]; + if (pAppName == NULL) + { + DbgTrace(0, "IpcServerInit- Memory allocation failure\n", 0); + goto exit; + } + strcpy(pAppName, pName); + + // Save the rest of the debug settings + DebugLevel = debugLevel; + UseSyslog = useSyslog; + + // Set to ignore SIGPIPE signals + signal(SIGPIPE, SIG_IGN); + + // Initialize our mutexes + pthread_mutex_init(&serverMutex, NULL); + pthread_mutex_init(&interlockedMutex, NULL); + + // Success + svcInitialized = true; + retStatus = 0; + +exit: + + DbgTrace(1, "IpcServerInit- End, retStatus = %08X\n", retStatus); + + return retStatus; + +} /*-- IpcServerInit() --*/ + + +//++======================================================================= +extern "C" +void +IpcServerShutdown(void) +// +// Arguments In: None. +// +// Arguments Out: None. +// +// Returns: Nothing. +// +// Abstract: Method to shutdown the IPC service. +// +// Note: +// +// L2 +//=======================================================================-- +{ + DbgTrace(1, "IpcServerShutdown- Start\n", 0); + + // Verify that we have been initialized + if (svcInitialized) + { + // We are being asked to terminate + terminating = true; + + // Abort all pending requests + AbortPendingRequests(); + + // Awaken any suspended server threads + AwakenSuspendedServerThreads(); + + // Wait for all of the active requests to complete + while (numActiveRequests) + sleep(1); + + // Close the listen socket if not already closed. This will + // cause the ServiceConnectionsThread to clean things up and + // shutdown. + if (listenSocket != INVALID_SOCKET) + { + // Close the socket + closesocket(listenSocket); + listenSocket = INVALID_SOCKET; + } + + // Forget about having being initialized + svcInitialized = false; + } + + // Free the AppName string if necessary + if (pAppName != unInitialized) + { + delete[] pAppName; + pAppName = unInitialized; + } + + // Forget about some things + serverAddressSet = false; + svcInitialized = false; + + DbgTrace(1, "IpcServerShutdown- End\n", 0); + +} /*-- IpcServerShutdown() --*/ + +//========================================================================= +//========================================================================= diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverreq.cpp b/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverreq.cpp new file mode 100644 index 00000000..dfa021ac --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverreq.cpp @@ -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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "ipcint.h" +#include "schannel.h" +#include "serverreq.h" +#include // 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() --*/ + + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverreq.h b/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverreq.h new file mode 100644 index 00000000..adb1ed5d --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverreq.h @@ -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 + * + ***********************************************************************/ + + +#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_ + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverthread.cpp b/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverthread.cpp new file mode 100644 index 00000000..7f7367a2 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverthread.cpp @@ -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 + * + ***********************************************************************/ + + +//===[ Include files ]===================================================== + +#include "ipcint.h" +#include "serverthread.h" +#include // 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() --*/ + + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverthread.h b/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverthread.h new file mode 100644 index 00000000..74d7f8dc --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/server/serverthread.h @@ -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 + * + ***********************************************************************/ + + +#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_ + +//========================================================================= +//========================================================================= + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/server/test/makeServer.sh b/CASA-auth-token/server/utilities/IpcLibs/linux/server/test/makeServer.sh new file mode 100755 index 00000000..2b565cd5 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/server/test/makeServer.sh @@ -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 + diff --git a/CASA-auth-token/server/utilities/IpcLibs/linux/server/test/testServer.c b/CASA-auth-token/server/utilities/IpcLibs/linux/server/test/testServer.c new file mode 100644 index 00000000..cf0d25c2 --- /dev/null +++ b/CASA-auth-token/server/utilities/IpcLibs/linux/server/test/testServer.c @@ -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 + * + ***********************************************************************/ + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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() --*/ + diff --git a/CASA-auth-token/server/utilities/Makefile.am b/CASA-auth-token/server/utilities/Makefile.am new file mode 100644 index 00000000..4430276e --- /dev/null +++ b/CASA-auth-token/server/utilities/Makefile.am @@ -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 +# +####################################################################### + +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 +