Initial changes for Linux port of the CASA-auth-token client to linux.
This commit is contained in:
		
							
								
								
									
										122
									
								
								CASA-auth-token/non-java/client/linux/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								CASA-auth-token/non-java/client/linux/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,122 @@ | ||||
| ####################################################################### | ||||
| # | ||||
| #  Copyright (C) 2006 Novell, Inc. | ||||
| # | ||||
| #  This program is free software; you can redistribute it and/or | ||||
| #  modify it under the terms of the GNU General Public | ||||
| #  License as published by the Free Software Foundation; either | ||||
| #  version 2 of the License, or (at your option) any later version. | ||||
| # | ||||
| #  This program is distributed in the hope that it will be useful, | ||||
| #  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
| #  General Public License for more details. | ||||
| # | ||||
| #  You should have received a copy of the GNU General Public | ||||
| #  License along with this program; if not, write to the Free | ||||
| #  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| # | ||||
| #  Author: Juan Carlos Luciani <jluciani@novell.com> | ||||
| # | ||||
| ####################################################################### | ||||
|  | ||||
| if DEBUG | ||||
| TARGET_CFG = Debug | ||||
| CFLAGS += -v -w | ||||
| else | ||||
| TARGET_CFG = Release | ||||
| 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 \ | ||||
| 	 rpc.c \ | ||||
| 	 platform.c | ||||
|  | ||||
| CSFILES_CSC := | ||||
| INCLUDES = -I. -I.. -I../../include | ||||
| RESOURCES = | ||||
| DEFINES = -fno-strict-aliasing  | ||||
| if LIB64 | ||||
| DEFINES += -D_LIB64 | ||||
| endif | ||||
| CFLAGS += $(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 | ||||
|  | ||||
							
								
								
									
										829
									
								
								CASA-auth-token/non-java/client/linux/platform.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										829
									
								
								CASA-auth-token/non-java/client/linux/platform.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,829 @@ | ||||
| /*********************************************************************** | ||||
|  *  | ||||
|  *  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.d/client.d"; | ||||
|  | ||||
| // Authentication mechanism configuration file folder | ||||
| char  mechConfigFolder[] = "/etc/CASA/authtoken.d/client.d/mechanisms.d"; | ||||
|  | ||||
| // 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). | ||||
| // | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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). | ||||
| // | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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). | ||||
| // | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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). | ||||
| // | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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: | ||||
| // | ||||
| // L1 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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(0, "-GetTickCount- TicksPerSec = %0X\n", ticksPerSecond); | ||||
|       g_milliSecondsPerTicks = 1000 / ticksPerSecond; | ||||
|    } | ||||
|  | ||||
|    // Determine the tickCount as milliseconds | ||||
|    tickCount = g_milliSecondsPerTicks * times(&tm); | ||||
|  | ||||
|    DbgTrace(2, "-GetTickCount- End, retValue = %0X\n", tickCount); | ||||
|  | ||||
|    return tickCount; | ||||
| } | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| CasaStatus | ||||
| CreateUserMutex( | ||||
|    HANDLE *phMutex | ||||
|    ) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L1 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    CasaStatus  retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, | ||||
|                                            CASA_FACILITY_AUTHTOKEN, | ||||
|                                            CASA_STATUS_UNSUCCESSFUL); | ||||
|  | ||||
|    DbgTrace(1, "-CreateUserMutex- Start\n", 0); | ||||
|  | ||||
|    // We use Posix 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); | ||||
|    } | ||||
|  | ||||
| exit: | ||||
|  | ||||
|    DbgTrace(1, "-CreateUserMutex- End, retStatus\n", retStatus); | ||||
|  | ||||
|    return retStatus; | ||||
| } | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| void | ||||
| AcquireUserMutex( | ||||
|    HANDLE hMutex | ||||
|    ) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L1 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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: | ||||
| // | ||||
| // L1 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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: | ||||
| // | ||||
| // L1 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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 (LocalSem_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 = %d\n", dlerror()); | ||||
|    } | ||||
|  | ||||
|    DbgTrace(1, "-OpenLibrary- End, handle = %08X\n", libHandle); | ||||
|  | ||||
|    return libHandle; | ||||
| } | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| void | ||||
| CloseLibrary( | ||||
|    IN    LIB_HANDLE libHandle) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L2 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    DbgTrace(1, "-CloseLibrary- Start\n", 0); | ||||
|  | ||||
|    dlclose(libHandle); | ||||
|  | ||||
|    DbgTrace(1, "-CloseLibrary- End\n", 0); | ||||
| } | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| void* | ||||
| GetFunctionPtr( | ||||
|    IN    LIB_HANDLE libHandle, | ||||
|    IN    char *pFunctionName) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L2 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    void  *pFuncPtr; | ||||
|  | ||||
|    DbgTrace(1, "-GetFunctionPtr- Start\n", 0); | ||||
|  | ||||
|    pFuncPtr = dlsym(libHandle, pFunctionName); | ||||
|    if (pFuncPtr == NULL) | ||||
|    { | ||||
|       DbgTrace(0, "-GetFunctionPtr- Not able to obtain func ptr, error = %d\n", dlerror()); | ||||
|    } | ||||
|  | ||||
|    DbgTrace(1, "-GetFunctionPtr- End, pFuncPtr = %08X\n", pFuncPtr); | ||||
|  | ||||
|    return pFuncPtr; | ||||
| } | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| char* | ||||
| NormalizeHostName( | ||||
|    IN    const char *pHostName) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L1 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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 = %08X\n", 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/non-java/client/linux/platform.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								CASA-auth-token/non-java/client/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; | ||||
|  | ||||
|  | ||||
| //========================================================================= | ||||
|  | ||||
							
								
								
									
										539
									
								
								CASA-auth-token/non-java/client/linux/rpc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										539
									
								
								CASA-auth-token/non-java/client/linux/rpc.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,539 @@ | ||||
| /*********************************************************************** | ||||
|  *  | ||||
|  *  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 INITIAL_RESPONSE_DATA_BUF_SIZE 1028 | ||||
| #define INCREMENT_RESPONSE_DATA_BUF_SIZE 256 | ||||
|  | ||||
| #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: | ||||
| // | ||||
| // L0 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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    char *pHostName, | ||||
|    IN    uint16_t hostPort) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L0 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    RpcSession  *pSession; | ||||
|    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 = %08X\n", pSession); | ||||
|  | ||||
|    return pSession; | ||||
| } | ||||
|  | ||||
|  | ||||
| //++======================================================================= | ||||
| void | ||||
| CloseRpcSession( | ||||
|    IN    RpcSession *pSession) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L1 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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    bool secure, | ||||
|    IN    char *pRequestData, | ||||
|    INOUT char **ppResponseData, | ||||
|    INOUT int *pResponseDataLen) | ||||
| // | ||||
| //  Arguments:  | ||||
| // | ||||
| //  Returns:    | ||||
| // | ||||
| //  Abstract:   | ||||
| // | ||||
| //  Notes: | ||||
| // | ||||
| // L1 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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 final URL using the input parameters | ||||
|    if (secure) | ||||
|    { | ||||
|       pPartialUrl = pSession->pPartialHttpsUrl; | ||||
|       partialUrlLen = pSession->partialHttpsUrlLen; | ||||
|    } | ||||
|    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 = %d\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    bool secure, | ||||
|    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, | ||||
|                               secure, | ||||
|                               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: | ||||
| // | ||||
| // L0 | ||||
| //=======================================================================-- | ||||
| { | ||||
|    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