Splitted the non-java project into client and server projects in order
to be able to deliver the client component onto distributions targeting desktops without having to deliver the server components. This commit is for the resulting client project.
This commit is contained in:
126
CASA-auth-token/client/core/linux/Makefile.am
Normal file
126
CASA-auth-token/client/core/linux/Makefile.am
Normal file
@@ -0,0 +1,126 @@
|
||||
#######################################################################
|
||||
#
|
||||
# Copyright (C) 2006 Novell, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public
|
||||
# License along with this program; if not, write to the Free
|
||||
# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
# Author: Juan Carlos Luciani <jluciani@novell.com>
|
||||
#
|
||||
#######################################################################
|
||||
|
||||
if DEBUG
|
||||
TARGET_CFG = Debug
|
||||
CFLAGS += -v -w
|
||||
DEFINES = -DDBG
|
||||
else
|
||||
TARGET_CFG = Release
|
||||
DEFINES = -DNDEBUG
|
||||
endif
|
||||
|
||||
SUBDIRS =
|
||||
|
||||
DIST_SUBDIRS =
|
||||
|
||||
ROOT = ../..
|
||||
|
||||
LIBDIR = $(ROOT)/$(LIB)
|
||||
|
||||
# handle Mono secondary dependencies
|
||||
export MONO_PATH := $(MONO_PATH)
|
||||
|
||||
PLATFORMINDEPENDENTSOURCEDIR = ..
|
||||
PLATFORMDEPENDENTSOURCEDIR = .
|
||||
|
||||
MODULE_NAME = libcasa_c_authtoken
|
||||
MODULE_EXT = so
|
||||
|
||||
CFILES = ../authmech.c \
|
||||
../authmsg.c \
|
||||
../authpolicy.c \
|
||||
../cache.c \
|
||||
../config.c \
|
||||
../engine.c \
|
||||
../getpolicymsg.c \
|
||||
../gettokenmsg.c \
|
||||
../util.c \
|
||||
../invalidcert.c \
|
||||
rpc.c \
|
||||
platform.c
|
||||
|
||||
CSFILES_CSC :=
|
||||
INCLUDES = -I. -I.. -I../../include
|
||||
RESOURCES =
|
||||
|
||||
if LIB64
|
||||
DEFINES += -D_LIB64
|
||||
endif
|
||||
|
||||
CFLAGS += -Wno-format-extra-args -fno-strict-aliasing $(INCLUDES) $(DEFINES)
|
||||
LIBS = -lpthread -ldl -lexpat -lcurl -lidn -lssl -lcrypto -lz -lmicasa
|
||||
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
|
||||
|
||||
831
CASA-auth-token/client/core/linux/platform.c
Normal file
831
CASA-auth-token/client/core/linux/platform.c
Normal file
@@ -0,0 +1,831 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, Novell, Inc.
|
||||
*
|
||||
* To contact Novell about this file by physical or electronic mail,
|
||||
* you may find current contact information at www.novell.com.
|
||||
*
|
||||
* Author: Juan Carlos Luciani <jluciani@novell.com>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
//===[ Include files ]=====================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
//
|
||||
// Normalized Host Name Cache Entry definition
|
||||
//
|
||||
typedef struct _NormalizedHostNameCacheEntry
|
||||
{
|
||||
LIST_ENTRY listEntry;
|
||||
char *pHostName;
|
||||
char *pNormalizedHostName;
|
||||
int buffLengthRequired;
|
||||
|
||||
} NormalizedHostNameCacheEntry, *PNormalizedHostNameCacheEntry;
|
||||
|
||||
|
||||
//===[ Type definitions for Local_sem ]====================================
|
||||
//
|
||||
// Notes: Most of the code for this definitions and the Local_sem_xxxx
|
||||
// functions was copied with minor modifications from W. Richard
|
||||
// Stevens book: UNIX Network Programming, Interprocess
|
||||
// Communications (Printed in 1999).
|
||||
//
|
||||
// You may ask, why not just use Posix Named Semaphores? The answer
|
||||
// is that I wish that I could but I can not tolerate that they are
|
||||
// not released when the process that holds them terminates abnormally.
|
||||
//
|
||||
|
||||
union semun /* define union for semctl() */
|
||||
{
|
||||
int val;
|
||||
struct semid_ds *buf;
|
||||
unsigned short *array;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int sem_semid; /* the System V semaphore ID */
|
||||
int sem_magic; /* magic number if open */
|
||||
|
||||
} Local_sem_t;
|
||||
|
||||
#ifndef SEM_R
|
||||
#define SEM_R 0400
|
||||
#endif
|
||||
|
||||
#ifndef SEM_A
|
||||
#define SEM_A 0200
|
||||
#endif
|
||||
|
||||
#define SVSEM_MODE (SEM_R | SEM_A | SEM_R>>3 | SEM_R>>6)
|
||||
|
||||
#define SEM_MAGIC 0x45678923
|
||||
|
||||
#define SEM_FAILED ((Local_sem_t *)(-1)) /* avoid compiler warnings */
|
||||
|
||||
#ifndef SEMVMX
|
||||
#define SEMVMX 32767 /* historical System V max value for sem */
|
||||
#endif
|
||||
|
||||
#define MAX_OPEN_SEM_TRIES 10 /* for waiting for initialization */
|
||||
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
// Normalized host name cache variables
|
||||
static
|
||||
LIST_ENTRY normalizedHostNameCacheListHead;
|
||||
|
||||
static
|
||||
pthread_mutex_t g_hNormalizedHostNameCacheMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
// Client configuration file folder
|
||||
char clientConfigFolder[] = "/etc/CASA/authtoken/client";
|
||||
|
||||
// Authentication mechanism configuration file folder
|
||||
char mechConfigFolder[] = "/etc/CASA/authtoken/client/mechanisms";
|
||||
|
||||
// Module Synchronization mutex
|
||||
pthread_mutex_t g_hModuleMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
// Path separator
|
||||
char pathCharString[] = "/";
|
||||
|
||||
// Milliseconds per System Tick
|
||||
static
|
||||
long g_milliSecondsPerTicks = 0;
|
||||
|
||||
// Named Semaphore for user variables
|
||||
static
|
||||
char g_userNamedSemName[256];
|
||||
|
||||
static
|
||||
Local_sem_t *g_userNamedSem = SEM_FAILED;
|
||||
|
||||
static
|
||||
bool g_userNamedSemAcquired = false;
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
Local_sem_t*
|
||||
Local_sem_open(const char *pathname, int oflag, ... )
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes: Most of the code for this routine was copied with minor
|
||||
// modifications from W. Richard Stevens book: UNIX Network
|
||||
// Programming, Interprocess Communications (Printed in 1999).
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
int i, fd, semflag, semid, save_errno;
|
||||
key_t key;
|
||||
mode_t mode;
|
||||
va_list ap;
|
||||
Local_sem_t *sem;
|
||||
union semun arg;
|
||||
unsigned int value;
|
||||
struct semid_ds seminfo;
|
||||
struct sembuf initop;
|
||||
|
||||
/* 4no mode for sem_open() w/out O_CREAT; guess */
|
||||
semflag = SVSEM_MODE;
|
||||
semid = -1;
|
||||
|
||||
if (oflag & O_CREAT) {
|
||||
va_start(ap, oflag); /* init ap to final named argument */
|
||||
mode = va_arg(ap, mode_t);
|
||||
value = va_arg(ap, unsigned int);
|
||||
va_end(ap);
|
||||
|
||||
/* 4convert to key that will identify System V semaphore */
|
||||
if ( (fd = open(pathname, oflag, mode)) == -1)
|
||||
return(SEM_FAILED);
|
||||
close(fd);
|
||||
if ( (key = ftok(pathname, 0)) == (key_t) -1)
|
||||
return(SEM_FAILED);
|
||||
|
||||
semflag = IPC_CREAT | (mode & 0777);
|
||||
if (oflag & O_EXCL)
|
||||
semflag |= IPC_EXCL;
|
||||
|
||||
/* 4create the System V semaphore with IPC_EXCL */
|
||||
if ( (semid = semget(key, 1, semflag | IPC_EXCL)) >= 0) {
|
||||
/* 4success, we're the first so initialize to 0 */
|
||||
arg.val = 0;
|
||||
if (semctl(semid, 0, SETVAL, arg) == -1)
|
||||
goto err;
|
||||
/* 4then increment by value to set sem_otime nonzero */
|
||||
if (value > SEMVMX) {
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
initop.sem_num = 0;
|
||||
initop.sem_op = value;
|
||||
initop.sem_flg = 0;
|
||||
if (semop(semid, &initop, 1) == -1)
|
||||
goto err;
|
||||
goto finish;
|
||||
|
||||
} else if (errno != EEXIST || (semflag & IPC_EXCL) != 0)
|
||||
goto err;
|
||||
/* else fall through */
|
||||
}
|
||||
|
||||
/*
|
||||
* (O_CREAT not secified) or
|
||||
* (O_CREAT without O_EXCL and semaphore already exists).
|
||||
* Must open semaphore and make certain it has been initialized.
|
||||
*/
|
||||
if ( (key = ftok(pathname, 0)) == (key_t) -1)
|
||||
goto err;
|
||||
if ( (semid = semget(key, 0, semflag)) == -1)
|
||||
goto err;
|
||||
|
||||
arg.buf = &seminfo;
|
||||
for (i = 0; i < MAX_OPEN_SEM_TRIES; i++) {
|
||||
if (semctl(semid, 0, IPC_STAT, arg) == -1)
|
||||
goto err;
|
||||
if (arg.buf->sem_otime != 0)
|
||||
goto finish;
|
||||
sleep(1);
|
||||
}
|
||||
errno = ETIMEDOUT;
|
||||
err:
|
||||
save_errno = errno; /* don't let semctl() change errno */
|
||||
if (semid != -1)
|
||||
semctl(semid, 0, IPC_RMID);
|
||||
errno = save_errno;
|
||||
return(SEM_FAILED);
|
||||
|
||||
finish:
|
||||
if ( (sem = malloc(sizeof(Local_sem_t))) == NULL)
|
||||
goto err;
|
||||
sem->sem_semid = semid;
|
||||
sem->sem_magic = SEM_MAGIC;
|
||||
return(sem);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
int
|
||||
Local_sem_wait(Local_sem_t *sem)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes: Most of the code for this routine was copied with minor
|
||||
// modifications from W. Richard Stevens book: UNIX Network
|
||||
// Programming, Interprocess Communications (Printed in 1999).
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
struct sembuf op;
|
||||
|
||||
if (sem->sem_magic != SEM_MAGIC) {
|
||||
errno = EINVAL;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
op.sem_num = 0;
|
||||
op.sem_op = -1;
|
||||
//op.sem_flg = 0;
|
||||
op.sem_flg = SEM_UNDO; // Deviation from Richard's to allow cleanup in case of abnormal termination.
|
||||
if (semop(sem->sem_semid, &op, 1) < 0)
|
||||
return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
int
|
||||
Local_sem_post(Local_sem_t *sem)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes: Most of the code for this routine was copied with minor
|
||||
// modifications from W. Richard Stevens book: UNIX Network
|
||||
// Programming, Interprocess Communications (Printed in 1999).
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
struct sembuf op;
|
||||
|
||||
if (sem->sem_magic != SEM_MAGIC) {
|
||||
errno = EINVAL;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
op.sem_num = 0;
|
||||
op.sem_op = 1;
|
||||
op.sem_flg = 0;
|
||||
if (semop(sem->sem_semid, &op, 1) < 0)
|
||||
return(-1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
int
|
||||
Local_sem_close(Local_sem_t *sem)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes: Most of the code for this routine was copied with minor
|
||||
// modifications from W. Richard Stevens book: UNIX Network
|
||||
// Programming, Interprocess Communications (Printed in 1999).
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
if (sem->sem_magic != SEM_MAGIC) {
|
||||
errno = EINVAL;
|
||||
return(-1);
|
||||
}
|
||||
sem->sem_magic = 0; /* just in case */
|
||||
|
||||
free(sem);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
DWORD
|
||||
GetTickCount(void)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
struct tms tm;
|
||||
DWORD tickCount;
|
||||
|
||||
DbgTrace(2, "-GetTickCount- Start\n", 0);
|
||||
|
||||
// Determine milliseconds per tick if we have not done already
|
||||
if (g_milliSecondsPerTicks == 0)
|
||||
{
|
||||
long ticksPerSecond;
|
||||
|
||||
ticksPerSecond = sysconf(_SC_CLK_TCK);
|
||||
DbgTrace(3, "-GetTickCount- TicksPerSec = %0lX\n", ticksPerSecond);
|
||||
g_milliSecondsPerTicks = 1000 / ticksPerSecond;
|
||||
}
|
||||
|
||||
// Determine the tickCount as milliseconds
|
||||
tickCount = g_milliSecondsPerTicks * times(&tm);
|
||||
|
||||
DbgTrace(2, "-GetTickCount- End, retValue = %0lX\n", tickCount);
|
||||
|
||||
return tickCount;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
CreateUserMutex(
|
||||
HANDLE *phMutex
|
||||
)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
|
||||
DbgTrace(1, "-CreateUserMutex- Start\n", 0);
|
||||
|
||||
// We use Named Semaphores to provide this functionality. The semaphore names are
|
||||
// linked to the user via its uid.
|
||||
if (sprintf(g_userNamedSemName, "/var/lib/CASA/authtoken/semuser_%d", geteuid()) != -1)
|
||||
{
|
||||
// Create or open semaphore to be only used by the effective user
|
||||
g_userNamedSem = Local_sem_open((const char*) g_userNamedSemName, O_RDWR | O_CREAT, 0600, 1);
|
||||
if (g_userNamedSem == SEM_FAILED)
|
||||
{
|
||||
DbgTrace(0, "-CreateUserMutex- Error opening named semaphore, errno = %d\n", errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-CreateUserMutex- sprintf failed, error = %d\n", errno);
|
||||
}
|
||||
|
||||
DbgTrace(1, "-CreateUserMutex- End, retStatus\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
AcquireUserMutex(
|
||||
HANDLE hMutex
|
||||
)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
DbgTrace(2, "-AcquireUserMutex- Start\n", 0);
|
||||
|
||||
// Wait on the named semaphore
|
||||
if (Local_sem_wait(g_userNamedSem) != 0)
|
||||
{
|
||||
DbgTrace(0, "-AcquireUserMutex- Error returned by sem_wait(), errno = %d\n", errno);
|
||||
}
|
||||
|
||||
// The user semaphore has been acquired
|
||||
g_userNamedSemAcquired = true;
|
||||
|
||||
DbgTrace(2, "-AcquireUserMutex- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
ReleaseUserMutex(
|
||||
HANDLE hMutex
|
||||
)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
DbgTrace(2, "-ReleaseUserMutex- Start\n", 0);
|
||||
|
||||
// The user semaphore is no longer acquired
|
||||
g_userNamedSemAcquired = false;
|
||||
|
||||
// Post on the named semaphore
|
||||
if (Local_sem_post(g_userNamedSem) != 0)
|
||||
{
|
||||
DbgTrace(0, "-ReleaseUserMutex- Error returned by sem_post(), errno = %d\n", errno);
|
||||
}
|
||||
|
||||
DbgTrace(2, "-ReleaseUserMutex- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
DestroyUserMutex(
|
||||
HANDLE hMutex
|
||||
)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
DbgTrace(2, "-DestroyUserMutex- Start\n", 0);
|
||||
|
||||
// Do not do anything if the named semaphore is invalid
|
||||
if (g_userNamedSem != SEM_FAILED)
|
||||
{
|
||||
// Close the named semaphore. Note that we want user semaphores to
|
||||
// hang around, therefore we will not unlink them. This is per-design as
|
||||
// is not a resource leak. If someone has an issue with this, then it can
|
||||
// be solved by installing a cron job that cleans up the semaphores for
|
||||
// deleted users.
|
||||
if (Local_sem_close(g_userNamedSem) != 0)
|
||||
{
|
||||
DbgTrace(0, "-DestroyUserMutex- Error returned by sem_close(), errno = %d\n", errno);
|
||||
}
|
||||
|
||||
// Forget about the semaphore
|
||||
g_userNamedSem = SEM_FAILED;
|
||||
}
|
||||
|
||||
DbgTrace(2, "-DestroyUserMutex- 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;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
char*
|
||||
NormalizeHostName(
|
||||
IN const char *pHostName)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
char *pNormalizedName = NULL;
|
||||
LIST_ENTRY *pListEntry;
|
||||
NormalizedHostNameCacheEntry *pEntry = NULL;
|
||||
|
||||
DbgTrace(1, "-NormalizeHostName- Start\n", 0);
|
||||
|
||||
// Obtain our synchronization mutex
|
||||
pthread_mutex_lock(&g_hNormalizedHostNameCacheMutex);
|
||||
|
||||
// First try to find an entry in the normalized host name cache
|
||||
// for the host name provided.
|
||||
pListEntry = normalizedHostNameCacheListHead.Flink;
|
||||
while (pListEntry != &normalizedHostNameCacheListHead)
|
||||
{
|
||||
// Get pointer to the entry
|
||||
pEntry = CONTAINING_RECORD(pListEntry, NormalizedHostNameCacheEntry, listEntry);
|
||||
|
||||
// Check if the entry is for the host name
|
||||
if (strcmp(pHostName, pEntry->pHostName) == 0)
|
||||
{
|
||||
// This entry corresponds to the given host name
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The entry does not correspond to the given host name
|
||||
pEntry = NULL;
|
||||
}
|
||||
|
||||
// Advance to the next entry
|
||||
pListEntry = pListEntry->Flink;
|
||||
}
|
||||
|
||||
// Check if we found an entry in our cache for the given host name
|
||||
if (pEntry)
|
||||
{
|
||||
// Entry found, obtain the normalized name from it.
|
||||
pNormalizedName = (char*) malloc(pEntry->buffLengthRequired);
|
||||
if (pNormalizedName)
|
||||
{
|
||||
// Copy the normalized name onto the allocated buffer
|
||||
strcpy(pNormalizedName, pEntry->pNormalizedHostName);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// An entry was not found in our cache, create one.
|
||||
pEntry = (NormalizedHostNameCacheEntry*) malloc(sizeof(NormalizedHostNameCacheEntry));
|
||||
if (pEntry)
|
||||
{
|
||||
// Zero the entry
|
||||
memset(pEntry, 0, sizeof(*pEntry));
|
||||
|
||||
// Allocate a buffer to hold the host name in the entry
|
||||
pEntry->pHostName = (char*) malloc(strlen(pHostName) + 1);
|
||||
if (pEntry->pHostName)
|
||||
{
|
||||
struct hostent *pLookupResult;
|
||||
struct sockaddr_in sockAddr = {0};
|
||||
|
||||
// Copy the host name given into the allocated buffer
|
||||
strcpy(pEntry->pHostName, pHostName);
|
||||
|
||||
// Now try to resolve the normalized name
|
||||
pLookupResult = gethostbyname(pHostName);
|
||||
if (pLookupResult && pLookupResult->h_addrtype == AF_INET)
|
||||
{
|
||||
char dnsHostName[NI_MAXHOST];
|
||||
|
||||
// Set up a sockaddr structure
|
||||
sockAddr.sin_family = AF_INET;
|
||||
sockAddr.sin_addr.s_addr = *((int*) pLookupResult->h_addr_list[0]);
|
||||
|
||||
// Now try to resolve the name using DNS
|
||||
if (getnameinfo((const struct sockaddr*) &sockAddr,
|
||||
sizeof(sockAddr),
|
||||
dnsHostName,
|
||||
sizeof(dnsHostName),
|
||||
NULL,
|
||||
0,
|
||||
NI_NAMEREQD) == 0)
|
||||
{
|
||||
// We resolved the address to a DNS name, use it as the normalized name.
|
||||
pEntry->buffLengthRequired = (int) strlen(dnsHostName) + 1;
|
||||
pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired);
|
||||
if (pEntry->pNormalizedHostName)
|
||||
{
|
||||
// Copy the dns name
|
||||
strcpy(pEntry->pNormalizedHostName, dnsHostName);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-NormalizeHostName- getnameInfo failed, error %d\n", errno);
|
||||
|
||||
// Not able to resolve the name in DNS, just use the host name as
|
||||
// the normalized name.
|
||||
pEntry->buffLengthRequired = (int) strlen(pHostName) + 1;
|
||||
pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired);
|
||||
if (pEntry->pNormalizedHostName)
|
||||
{
|
||||
// Copy the host name
|
||||
strcpy(pEntry->pNormalizedHostName, pHostName);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-NormalizeHostName- Name resolution failed, error = %d\n", errno);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0);
|
||||
|
||||
// Free the space allocated for the entry
|
||||
free(pEntry);
|
||||
}
|
||||
|
||||
// Proceed based on whether or not we normalized the name
|
||||
if (pEntry->pNormalizedHostName)
|
||||
{
|
||||
// The name was normalized, save the entry in our cache.
|
||||
InsertHeadList(&normalizedHostNameCacheListHead, &pEntry->listEntry);
|
||||
|
||||
// Return the normalized name present in the entry
|
||||
pNormalizedName = (char*) malloc(pEntry->buffLengthRequired);
|
||||
if (pNormalizedName)
|
||||
{
|
||||
// Copy the normalized name onto the allocated buffer
|
||||
strcpy(pNormalizedName, pEntry->pNormalizedHostName);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The host name was not normalized, free allocated resources.
|
||||
if (pEntry->pHostName)
|
||||
free(pEntry->pHostName);
|
||||
free(pEntry);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Release our synchronization mutex
|
||||
pthread_mutex_unlock(&g_hNormalizedHostNameCacheMutex);
|
||||
|
||||
DbgTrace(1, "-NormalizeHostName- End, pNormalizedName = %0lX\n", (long) pNormalizedName);
|
||||
|
||||
return pNormalizedName;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
InitializeHostNameNormalization(void)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus = CASA_STATUS_SUCCESS;
|
||||
|
||||
DbgTrace(1, "-InitializeHostNameNormalization- Start\n", 0);
|
||||
|
||||
// Initialize the cache list head
|
||||
InitializeListHead(&normalizedHostNameCacheListHead);
|
||||
|
||||
DbgTrace(1, "-InitializeHostNameNormalization- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
130
CASA-auth-token/client/core/linux/platform.h
Normal file
130
CASA-auth-token/client/core/linux/platform.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, Novell, Inc.
|
||||
*
|
||||
* To contact Novell about this file by physical or electronic mail,
|
||||
* you may find current contact information at www.novell.com.
|
||||
*
|
||||
* Author: Juan Carlos Luciani <jluciani@novell.com>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
//===[ Include files ]=====================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/times.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <curl/curl.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
#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_AuthToken %s", printBuff); \
|
||||
} \
|
||||
}
|
||||
/*#define DbgTrace(LEVEL, X, Y) { \
|
||||
if (LEVEL == 0 || DebugLevel >= LEVEL) \
|
||||
{ \
|
||||
openlog("CASA_AuthToken", LOG_CONS | LOG_NOWAIT | LOG_ODELAY, LOG_USER); \
|
||||
syslog(LOG_USER | LOG_INFO, X, Y); \
|
||||
closelog(); \
|
||||
} \
|
||||
}*/
|
||||
|
||||
|
||||
//
|
||||
// Rpc Session definition
|
||||
//
|
||||
typedef struct _RpcSession
|
||||
{
|
||||
CURL *hCurl;
|
||||
char *pPartialHttpUrl;
|
||||
int partialHttpUrlLen;
|
||||
char *pPartialHttpsUrl;
|
||||
int partialHttpsUrlLen;
|
||||
struct curl_slist *headers;
|
||||
char *pRecvData;
|
||||
int recvDataLen;
|
||||
|
||||
} RpcSession, *PRpcSession;
|
||||
|
||||
|
||||
//
|
||||
// Other definitions
|
||||
//
|
||||
#define HANDLE void*
|
||||
#define LIB_HANDLE void*
|
||||
#define DWORD unsigned long
|
||||
|
||||
#define AcquireModuleMutex pthread_mutex_lock(&g_hModuleMutex)
|
||||
#define ReleaseModuleMutex pthread_mutex_unlock(&g_hModuleMutex)
|
||||
|
||||
//
|
||||
// Deal with function name mapping issues
|
||||
//
|
||||
#define _snprintf snprintf
|
||||
#define stricmp strcasecmp
|
||||
|
||||
|
||||
//===[ Inlines functions ]===============================================
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global externals ]==================================================
|
||||
|
||||
//===[ External prototypes ]===============================================
|
||||
|
||||
extern
|
||||
DWORD
|
||||
GetTickCount(void);
|
||||
|
||||
//===[ External data ]=====================================================
|
||||
|
||||
extern pthread_mutex_t g_hModuleMutex;
|
||||
|
||||
|
||||
//=========================================================================
|
||||
|
||||
566
CASA-auth-token/client/core/linux/rpc.c
Normal file
566
CASA-auth-token/client/core/linux/rpc.c
Normal file
@@ -0,0 +1,566 @@
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, Novell, Inc.
|
||||
*
|
||||
* To contact Novell about this file by physical or electronic mail,
|
||||
* you may find current contact information at www.novell.com.
|
||||
*
|
||||
* Author: Juan Carlos Luciani <jluciani@novell.com>
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
//===[ Include files ]=====================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
//===[ Type definitions ]==================================================
|
||||
|
||||
#define MAX_RPC_RETRIES 3
|
||||
|
||||
//===[ Function prototypes ]===============================================
|
||||
|
||||
//===[ Global variables ]==================================================
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
size_t
|
||||
CurlWriteCallback(
|
||||
IN void *pData,
|
||||
IN size_t dataItemSz,
|
||||
IN size_t numDataItems,
|
||||
IN RpcSession *pSession)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
size_t dataConsumed = numDataItems;
|
||||
|
||||
DbgTrace(1, "-CurlWriteCallback- Start\n", 0);
|
||||
|
||||
// Consume the data by keeping a copy of the data. Note that we may have
|
||||
// already consumed some data in which case we need to allocate a new
|
||||
// buffer big enough to hold all of it.
|
||||
if (pSession->pRecvData == NULL)
|
||||
{
|
||||
// We have not yet consumed receive data for the current Rpc
|
||||
pSession->pRecvData = (char*) malloc(numDataItems * dataItemSz);
|
||||
if (pSession->pRecvData)
|
||||
{
|
||||
// Consume the data
|
||||
memcpy(pSession->pRecvData, pData, numDataItems * dataItemSz);
|
||||
pSession->recvDataLen = numDataItems * dataItemSz;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-CurlWriteCallback- Buffer allocation error\n", 0);
|
||||
dataConsumed = CURLE_WRITE_ERROR; // To abort RPC
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have already consumed receive data for the current Rpc, append the new data to it.
|
||||
char *pNewRecvDataBuf = (char*) malloc(pSession->recvDataLen + (numDataItems * dataItemSz));
|
||||
if (pNewRecvDataBuf)
|
||||
{
|
||||
memcpy(pNewRecvDataBuf, pSession->pRecvData, pSession->recvDataLen);
|
||||
memcpy(pNewRecvDataBuf + pSession->recvDataLen, pData, numDataItems * dataItemSz);
|
||||
pSession->recvDataLen += numDataItems * dataItemSz;
|
||||
free(pSession->pRecvData);
|
||||
pSession->pRecvData = pNewRecvDataBuf;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-CurlWriteCallback- Buffer allocation error\n", 0);
|
||||
dataConsumed = CURLE_WRITE_ERROR; // To abort RPC
|
||||
|
||||
// Forget about already consumed data
|
||||
free(pSession->pRecvData);
|
||||
pSession->pRecvData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DbgTrace(1, "-CurlWriteCallback- End\n", 0);
|
||||
|
||||
return dataConsumed;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
RpcSession*
|
||||
OpenRpcSession(
|
||||
IN const char *pHostName,
|
||||
IN const uint16_t hostPort)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
RpcSession *pSession = NULL;
|
||||
char *pPartialHttpUrl = NULL;
|
||||
char *pPartialHttpsUrl = NULL;
|
||||
int hostNameLen = strlen(pHostName);
|
||||
|
||||
DbgTrace(1, "-OpenRpcSession- Start\n", 0);
|
||||
|
||||
// Build the partial URL strings that may be used with this session.
|
||||
pPartialHttpUrl = (char*) malloc(7 /*"http://"*/ + hostNameLen + 34 /*":XXXX/CasaAuthTokenSvc/Rpc?method="*/ + 1 /*NULL Terminator*/);
|
||||
pPartialHttpsUrl = (char*) malloc(8 /*"https://"*/ + hostNameLen + 34 /*":XXXX/CasaAuthTokenSvc/Rpc?method="*/ + 1 /*NULL Terminator*/);
|
||||
if (pPartialHttpUrl && pPartialHttpsUrl)
|
||||
{
|
||||
sprintf(pPartialHttpUrl, "http://%s:%d/CasaAuthTokenSvc/Rpc?method=", pHostName, hostPort);
|
||||
sprintf(pPartialHttpsUrl, "https://%s:%d/CasaAuthTokenSvc/Rpc?method=", pHostName, hostPort);
|
||||
|
||||
// Allocate space for the session
|
||||
pSession = (RpcSession*) malloc(sizeof(*pSession));
|
||||
if (pSession)
|
||||
{
|
||||
// Zero the session structure
|
||||
memset(pSession, 0, sizeof(*pSession));
|
||||
|
||||
// Get a curl handle
|
||||
pSession->hCurl = curl_easy_init();
|
||||
if (pSession->hCurl != NULL)
|
||||
{
|
||||
CURLcode result;
|
||||
bool setOptError = false;
|
||||
|
||||
// Set necessary options on the handle
|
||||
if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_NOSIGNAL, 0)) != CURLE_OK)
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_NOSIGNAL, code = %d\n", result);
|
||||
setOptError = true;
|
||||
}
|
||||
|
||||
if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_USERAGENT, "CASA Client/1.0")) != CURLE_OK)
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_USERAGENT, code = %d\n", result);
|
||||
setOptError = true;
|
||||
}
|
||||
|
||||
if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_POST, 1)) != CURLE_OK)
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_POST, code = %d\n", result);
|
||||
setOptError = true;
|
||||
}
|
||||
|
||||
pSession->headers = curl_slist_append(pSession->headers, "Content-Type: text/html");
|
||||
pSession->headers = curl_slist_append(pSession->headers, "Expect:");
|
||||
if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_HTTPHEADER, pSession->headers)) != CURLE_OK)
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_HTTPHEADER, code = %d\n", result);
|
||||
setOptError = true;
|
||||
}
|
||||
|
||||
if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_WRITEFUNCTION, CurlWriteCallback)) != CURLE_OK)
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_WRITEFUNCTION, code = %d\n", result);
|
||||
setOptError = true;
|
||||
}
|
||||
|
||||
if ((result = curl_easy_setopt(pSession->hCurl, CURLOPT_WRITEDATA, pSession)) != CURLE_OK)
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_WRITEDATA, code = %d\n", result);
|
||||
setOptError = true;
|
||||
}
|
||||
|
||||
// Now check if we succeded
|
||||
if (setOptError == false)
|
||||
{
|
||||
// Success, finish setting up the session object.
|
||||
pSession->pPartialHttpUrl = pPartialHttpUrl;
|
||||
pSession->partialHttpUrlLen = strlen(pPartialHttpUrl);
|
||||
pSession->pPartialHttpsUrl = pPartialHttpsUrl;
|
||||
pSession->partialHttpsUrlLen = strlen(pPartialHttpsUrl);
|
||||
|
||||
// Forget about the partial URL buffers so that they do not get deleted below
|
||||
pPartialHttpUrl = NULL;
|
||||
pPartialHttpsUrl = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to set a needed curl option
|
||||
if (pSession->headers)
|
||||
curl_slist_free_all(pSession->headers);
|
||||
|
||||
curl_easy_cleanup(pSession->hCurl);
|
||||
|
||||
free(pSession);
|
||||
pSession = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error creating curl handle\n", 0);
|
||||
free(pSession);
|
||||
pSession = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for rpc session\n", 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for URL\n", 0);
|
||||
}
|
||||
|
||||
// Free buffers not utilized
|
||||
if (pPartialHttpUrl)
|
||||
free(pPartialHttpUrl);
|
||||
|
||||
if (pPartialHttpsUrl)
|
||||
free(pPartialHttpsUrl);
|
||||
|
||||
DbgTrace(2, "-OpenRpcSession- End, pSession = %0lX\n", (long) pSession);
|
||||
|
||||
return pSession;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
void
|
||||
CloseRpcSession(
|
||||
IN RpcSession *pSession)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
DbgTrace(1, "-CloseRpcSession- Start\n", 0);
|
||||
|
||||
// Free any HTTP headers associated with the session
|
||||
if (pSession->headers)
|
||||
curl_slist_free_all(pSession->headers);
|
||||
|
||||
// Close the curl handle associated with this session
|
||||
curl_easy_cleanup(pSession->hCurl);
|
||||
|
||||
// Free the space allocated for the session
|
||||
if (pSession->pRecvData)
|
||||
free(pSession->pRecvData);
|
||||
|
||||
free(pSession->pPartialHttpUrl);
|
||||
free(pSession->pPartialHttpsUrl);
|
||||
|
||||
free(pSession);
|
||||
|
||||
DbgTrace(1, "-CloseRpcSession- End\n", 0);
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
static
|
||||
CasaStatus
|
||||
InternalRpc(
|
||||
IN RpcSession *pSession,
|
||||
IN char *pMethod,
|
||||
IN long flags,
|
||||
IN char *pRequestData,
|
||||
INOUT char **ppResponseData,
|
||||
INOUT int *pResponseDataLen)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
#define CASA_STATUS_INVALID_SERVER_CERTIFICATE CASA_STATUS_UNSUCCESSFUL // temporary until casa_status.h is updated
|
||||
|
||||
CasaStatus retStatus;
|
||||
char *pPartialUrl;
|
||||
int partialUrlLen;
|
||||
char *pUrl;
|
||||
CURLcode curlResult;
|
||||
|
||||
DbgTrace(1, "-InternalRpc- Start\n", 0);
|
||||
|
||||
// Initialize output parameters
|
||||
*ppResponseData = NULL;
|
||||
*pResponseDataLen = 0;
|
||||
|
||||
// Setup the URL using the input parameters
|
||||
if (flags & SECURE_RPC_FLAG)
|
||||
{
|
||||
pPartialUrl = pSession->pPartialHttpsUrl;
|
||||
partialUrlLen = pSession->partialHttpsUrlLen;
|
||||
|
||||
// Check if we need to ignore invalid CERTS
|
||||
if (flags & ALLOW_INVALID_CERTS_RPC_FLAG)
|
||||
{
|
||||
if ((curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_SSL_VERIFYPEER, 0)) != CURLE_OK)
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Error setting CURLOPT_SSL_VERIFYPEER, code = %d\n", curlResult);
|
||||
}
|
||||
|
||||
if ((curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_SSL_VERIFYHOST, 0)) != CURLE_OK)
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Error setting CURLOPT_SSL_VERIFYHOST, code = %d\n", curlResult);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_SSL_VERIFYPEER, 1)) != CURLE_OK)
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Error setting CURLOPT_SSL_VERIFYPEER, code = %d\n", curlResult);
|
||||
}
|
||||
|
||||
if ((curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_SSL_VERIFYHOST, 2)) != CURLE_OK)
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Error setting CURLOPT_SSL_VERIFYHOST, code = %d\n", curlResult);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
pPartialUrl = pSession->pPartialHttpUrl;
|
||||
partialUrlLen = pSession->partialHttpUrlLen;
|
||||
}
|
||||
|
||||
pUrl = (char*) malloc(partialUrlLen + strlen(pMethod) + 1);
|
||||
|
||||
if (pUrl)
|
||||
{
|
||||
strcpy(pUrl, pPartialUrl);
|
||||
strcat(pUrl, pMethod);
|
||||
|
||||
// Tell curl about the URL
|
||||
curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_URL, pUrl);
|
||||
if (curlResult == CURLE_OK)
|
||||
{
|
||||
// Tell curl about our post data
|
||||
curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_POSTFIELDS, pRequestData);
|
||||
if (curlResult == CURLE_OK)
|
||||
{
|
||||
// Tell curl about our post data len
|
||||
curlResult = curl_easy_setopt(pSession->hCurl, CURLOPT_POSTFIELDSIZE, strlen(pRequestData));
|
||||
if (curlResult == CURLE_OK)
|
||||
{
|
||||
// Now do the HTTP request
|
||||
curlResult = curl_easy_perform(pSession->hCurl);
|
||||
if (curlResult == CURLE_OK)
|
||||
{
|
||||
// Get the HTTP Response code
|
||||
long httpCompStatus;
|
||||
curlResult = curl_easy_getinfo(pSession->hCurl, CURLINFO_RESPONSE_CODE, &httpCompStatus);
|
||||
if (curlResult == CURLE_OK)
|
||||
{
|
||||
// Verify that the HTTP request was successfully completed by the server
|
||||
if (httpCompStatus == 200)
|
||||
{
|
||||
// Success, return the response data to the caller.
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
*ppResponseData = pSession->pRecvData;
|
||||
*pResponseDataLen = pSession->recvDataLen;;
|
||||
|
||||
// Forget about the response data buffer to keep from freeing it.
|
||||
pSession->pRecvData = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- HTTP request did not complete successfully, status = %ld\n", httpCompStatus);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Curl get info failed, code = %d\n", curlResult);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Curl perform failed, code = %d\n", curlResult);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
// Make sure that we never exit with a recv data buffer hanging off the session
|
||||
if (pSession->pRecvData)
|
||||
{
|
||||
free(pSession->pRecvData);
|
||||
pSession->pRecvData = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_POSTFIELDSIZE, code = %d\n", curlResult);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_POSTFIELDS, code = %d\n", curlResult);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-OpenRpcSession- Error setting CURLOPT_URL, code = %d\n", curlResult);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
// Free the buffer used to hold the URL
|
||||
free(pUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgTrace(0, "-InternalRpc- Buffer allocation failure\n", 0);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
DbgTrace(1, "-InternalRpc- End, retStatus = %d\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
Rpc(
|
||||
IN RpcSession *pSession,
|
||||
IN char *pMethod,
|
||||
IN long flags,
|
||||
IN char *pRequestData,
|
||||
INOUT char **ppResponseData,
|
||||
INOUT int *pResponseDataLen)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
int retries = 0;
|
||||
|
||||
DbgTrace(1, "-Rpc- Start\n", 0);
|
||||
|
||||
// Retry the RPC as needed
|
||||
do
|
||||
{
|
||||
// Issue the RPC
|
||||
retStatus = InternalRpc(pSession,
|
||||
pMethod,
|
||||
flags,
|
||||
pRequestData,
|
||||
ppResponseData,
|
||||
pResponseDataLen);
|
||||
|
||||
// Account for this try
|
||||
retries ++;
|
||||
|
||||
} while (CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE
|
||||
&& retries < MAX_RPC_RETRIES);
|
||||
|
||||
DbgTrace(1, "-Rpc- End, retStatus = %d\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
CasaStatus
|
||||
InitializeRpc(void)
|
||||
//
|
||||
// Arguments:
|
||||
//
|
||||
// Returns:
|
||||
//
|
||||
// Abstract:
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// L2
|
||||
//=======================================================================--
|
||||
{
|
||||
CasaStatus retStatus;
|
||||
|
||||
DbgTrace(1, "-InitializeRpc- Start\n", 0);
|
||||
|
||||
// Perform libcurl initializatoin
|
||||
CURLcode curlStatus = curl_global_init(CURL_GLOBAL_SSL);
|
||||
if (curlStatus != 0)
|
||||
{
|
||||
DbgTrace(0, "-InitializeRpc- Error initializing libcurl, curlStatus = %08X\n", curlStatus);
|
||||
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
||||
CASA_FACILITY_AUTHTOKEN,
|
||||
CASA_STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Success
|
||||
retStatus = CASA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DbgTrace(1, "-InitializeRpc- End, retStatus = %08X\n", retStatus);
|
||||
|
||||
return retStatus;
|
||||
}
|
||||
|
||||
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
//++=======================================================================
|
||||
|
||||
Reference in New Issue
Block a user