summaryrefslogtreecommitdiff
path: root/libapoc/papiPort.c
diff options
context:
space:
mode:
Diffstat (limited to 'libapoc/papiPort.c')
-rw-r--r--libapoc/papiPort.c457
1 files changed, 457 insertions, 0 deletions
diff --git a/libapoc/papiPort.c b/libapoc/papiPort.c
new file mode 100644
index 0000000..f19926e
--- /dev/null
+++ b/libapoc/papiPort.c
@@ -0,0 +1,457 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either
+ * the GNU General Public License Version 2 only ("GPL") or
+ * the Common Development and Distribution License("CDDL")
+ * (collectively, the "License"). You may not use this file
+ * except in compliance with the License. You can obtain a copy
+ * of the License at www.sun.com/CDDL or at COPYRIGHT. See the
+ * License for the specific language governing permissions and
+ * limitations under the License. When distributing the software,
+ * include this License Header Notice in each file and include
+ * the License file at /legal/license.txt. If applicable, add the
+ * following below the License Header, with the fields enclosed
+ * by brackets [] replaced by your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by
+ * only the CDDL or only the GPL Version 2, indicate your
+ * decision by adding "[Contributor] elects to include this
+ * software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice
+ * of license, a recipient has the option to distribute your
+ * version of this file under either the CDDL, the GPL Version
+ * 2 or to extend the choice of license to its licensees as
+ * provided above. However, if you add GPL Version 2 code and
+ * therefore, elected the GPL Version 2 license, then the
+ * option applies only if the new code is made subject to such
+ * option by the copyright holder.
+ */
+#include "papiUtils.h"
+#include "config.h"
+
+#include <gssapi.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef SOLARIS
+#include <libscf.h>
+#endif
+
+static void initGSSAPIContext( const char * inServiceName,
+ gss_ctx_id_t * outContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus );
+
+static int isDaemonInitdEnabled( void );
+
+static void writeGSSAPIAuthId( gss_ctx_id_t * outContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus );
+
+const char * getGSSAPISrcName( gss_ctx_id_t * inContext );
+
+static void getTargetService( const char * inServiceName,
+ gss_name_t * outService,
+ PAPIStatus * outStatus );
+
+static void encodeGSSAPITokens( gss_buffer_desc * inBuffers,
+ int inBufferCnt,
+ char ** outB64 );
+
+static const char * sInstallDir = APOC_INSTALLDIR;
+static const char * sLibraryDir = APOC_LIBRARYDIR;
+static const char * sPropertiesDir = APOC_PROPDIR;
+
+
+PAPIThread createThread( PAPIThreadFunc inThreadFunc, void * inArg )
+{
+ pthread_attr_t theAttr;
+ pthread_t * theThread = ( pthread_t * )malloc( sizeof( pthread_t ) );
+
+ pthread_attr_init( &theAttr );
+ pthread_attr_setdetachstate( &theAttr, PTHREAD_CREATE_DETACHED );
+ if ( pthread_create( theThread, &theAttr, inThreadFunc, inArg ) != 0 )
+ {
+ free( ( void * )theThread );
+ theThread = 0;
+ }
+ return theThread;
+}
+
+void destroyThread( PAPIThread inThread )
+{
+ pthread_cancel( *inThread );
+}
+
+void deleteMutex( PAPIMutex * inMutex )
+{
+ if ( inMutex != 0 )
+ {
+ pthread_mutex_destroy( inMutex );
+ free( ( void * )inMutex );
+ }
+}
+
+const char * getSASLCreds( const char * inServiceName, PAPIStatus * outStatus )
+{
+ char * theCredentials = 0;
+ gss_ctx_id_t theContextHandle = GSS_C_NO_CONTEXT;
+ gss_buffer_desc theOutputTokens[ 3 ];
+
+ theOutputTokens[ 0 ].length =
+ theOutputTokens[ 1 ].length =
+ theOutputTokens[ 2 ].length = 0;
+ initGSSAPIContext( inServiceName,
+ &theContextHandle,
+ &theOutputTokens[ 0 ],
+ outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ writeGSSAPIAuthId( &theContextHandle, &theOutputTokens[ 2 ],outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ OM_uint32 theMinorStatus;
+ encodeGSSAPITokens( theOutputTokens,
+ 3,
+ &theCredentials );
+ gss_release_buffer( &theMinorStatus, &theOutputTokens[ 0 ] );
+ gss_release_buffer( &theMinorStatus, &theOutputTokens[ 2 ] );
+ gss_delete_sec_context( &theMinorStatus,
+ &theContextHandle,
+ 0 );
+ }
+ }
+ return theCredentials;
+}
+
+const char * getInstallDir( void )
+{
+ return sInstallDir;
+}
+
+const char * getLibraryDir( void )
+{
+ return sLibraryDir;
+}
+
+const char * getPropertiesDir( void )
+{
+ return sPropertiesDir;
+}
+
+const char * getUserName( void )
+{
+/*
+ * no longer using cuserid here as it truncates user name at 8 characters
+ */
+ struct passwd * thePasswd = getpwuid( geteuid() );
+ return thePasswd != 0 && thePasswd->pw_name != 0 ?
+ strdup( thePasswd->pw_name ) : 0;
+}
+
+int isDaemonEnabled( void )
+{
+ int isDaemonEnabled = 0;
+#ifdef SOLARIS
+ isDaemonEnabled = isServiceEnabled();
+#else
+ isDaemonEnabled = isDaemonInitdEnabled();
+#endif
+ return isDaemonEnabled;
+}
+
+#ifdef SOLARIS
+int isServiceEnabled( void )
+{
+ static const char * sInstanceName = "svc:/network/apocd/udp:default";
+ int isServiceEnabled = 0;
+ char * theState = smf_get_state( sInstanceName );
+ if ( theState != 0 )
+ {
+ if ( strcmp( theState, SCF_STATE_STRING_DISABLED ) != 0 )
+ {
+ isServiceEnabled = 1;
+ }
+ free( ( void * )theState );
+ }
+ return isServiceEnabled;
+}
+#else
+int isDaemonInitdEnabled( void )
+{
+ static char * theCommand = "/sbin/chkconfig -c apocd";
+ FILE * theStream;
+ int theRC = 0;
+
+ theStream = papiPopen( theCommand, "w" );
+ if ( theStream != 0 )
+ {
+ theRC = papiPclose( theStream ) == 0 ? 1 : 0;
+ }
+
+ return theRC;
+}
+#endif
+
+int lockMutex( PAPIMutex * inMutex )
+{
+ return pthread_mutex_lock( inMutex );
+}
+
+PAPIMutex * newMutex( void )
+{
+ pthread_mutex_t * theMutex =
+ ( pthread_mutex_t * )malloc( sizeof( pthread_mutex_t ) );
+ if ( theMutex != 0 )
+ {
+ pthread_mutex_init( theMutex, 0 );
+ }
+ return theMutex;
+}
+
+int socketPoll( PAPISocket inSocket, int inMillis )
+{
+ struct pollfd thePollFD;
+ int theRC;
+
+ thePollFD.fd = inSocket;
+ thePollFD.events = POLLIN;
+ theRC = poll( &thePollFD, 1, inMillis );
+ if ( theRC == 1 && thePollFD.revents & POLLIN != POLLIN )
+ {
+ theRC = 0;
+ }
+ else if ( theRC == -1 && thePollFD.revents & POLLHUP == POLLHUP )
+ {
+ theRC = 0;
+ }
+
+ return theRC;
+}
+
+int startDaemon( void )
+{
+ int theRC = 1;
+
+ /*
+ * apoc2.0: daemon startup via inetd no longer supported
+ *
+ if ( isDaemonEnabled() == 1 )
+ {
+ int theSocket = getConnectedSocket( getDaemonPort(), SOCK_DGRAM, 0 );
+ if ( theSocket != INVALID_SOCKET )
+ {
+ if ( send( theSocket, ( void *)"\n", 1, 0 ) != -1 )
+ {
+ theRC = 0;
+ }
+ close( theSocket );
+ }
+ }
+ */
+ return theRC;
+}
+
+int unlockMutex( PAPIMutex * inMutex )
+{
+ return pthread_mutex_unlock( inMutex );
+}
+
+void encodeGSSAPITokens( gss_buffer_desc * inBuffers,
+ int inBufferCnt,
+ char ** outB64Buffer )
+{
+ void * theBuffer;
+ char * theTmpPtr;
+ int theBufferSize = 0;
+ int theIndex;
+
+ for ( theIndex = 0; theIndex < inBufferCnt; ++ theIndex )
+ {
+ theBufferSize += inBuffers[ theIndex ].length + 5;
+ }
+
+ theBuffer = malloc( theBufferSize );
+ theTmpPtr = ( char *)theBuffer;
+ for ( theIndex = 0; theIndex < inBufferCnt; ++ theIndex )
+ {
+ /* Write the token size */
+ snprintf( theTmpPtr, 6, "%05d", inBuffers[ theIndex ].length );
+ theTmpPtr += 5;
+
+ /* Write the token */
+ memcpy( ( void *)theTmpPtr,
+ inBuffers[ theIndex ].value,
+ inBuffers[ theIndex ].length);
+ theTmpPtr += inBuffers[ theIndex ].length;
+ }
+ base64_encode( theBuffer, theBufferSize, outB64Buffer );
+ free( ( void *)theBuffer );
+}
+
+void initGSSAPIContext( const char * inServiceName,
+ gss_ctx_id_t * outContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus )
+{
+ gss_name_t theServiceName;
+
+ getTargetService( inServiceName, &theServiceName, outStatus );
+ if ( *outStatus == PAPISuccess )
+ {
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_buffer_desc theServiceNameBuf;
+ OM_uint32 theReqFlags = GSS_C_DELEG_FLAG;
+ OM_uint32 theRetFlags;
+ gss_OID theMech;
+#ifdef SOLARIS
+ gss_OID_desc theMechArr =
+ { 9, "\052\206\110\206\367\022\001\002\002"};
+ theMech = &theMechArr;
+#else
+ theMech = GSS_KRB5_MECHANISM;
+#endif
+
+ outToken->length = 0;
+ theMajorStatus = gss_init_sec_context( &theMinorStatus,
+ GSS_C_NO_CREDENTIAL,
+ outContext,
+ theServiceName,
+ GSS_C_NO_OID,
+ 0,
+ 0,
+ NULL,
+ GSS_C_NO_BUFFER,
+ 0,
+ outToken,
+ &theRetFlags,
+ 0 );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ *outStatus = PAPISuccess;
+ }
+ else
+ {
+ *outStatus = PAPIAuthenticationFailure;
+ }
+ }
+}
+
+const char * getGSSAPISrcName( gss_ctx_id_t * inContext )
+{
+ char * theGSSAPISrcName = 0;
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_name_t theSrcName;
+
+ theMajorStatus = gss_inquire_context( &theMinorStatus,
+ *inContext,
+ &theSrcName,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0 );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ gss_buffer_desc theSrcNameBuffer;
+ theMajorStatus = gss_display_name( &theMinorStatus,
+ theSrcName,
+ &theSrcNameBuffer,
+ 0 );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ int theSize = theSrcNameBuffer.length + 1;
+ theGSSAPISrcName = ( char * )malloc( theSize );
+ if ( theGSSAPISrcName != 0 )
+ {
+ snprintf( theGSSAPISrcName,
+ theSize,
+ "%s",
+ ( char *)theSrcNameBuffer.value );
+ }
+ gss_release_buffer( &theMinorStatus, &theSrcNameBuffer );
+ }
+ }
+ return theGSSAPISrcName;
+}
+
+void getTargetService( const char * inServiceName,
+ gss_name_t * outServiceName,
+ PAPIStatus * outStatus )
+{
+ if ( inServiceName != 0 )
+ {
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_buffer_desc theServiceNameBuf;
+ OM_uint32 theReqFlags = GSS_C_DELEG_FLAG;
+ OM_uint32 theRetFlags;
+
+ theServiceNameBuf.length = strlen( inServiceName );
+ theServiceNameBuf.value = ( char * )inServiceName;
+ theMajorStatus =
+ gss_import_name( &theMinorStatus,
+ &theServiceNameBuf,
+ GSS_C_NO_OID,
+ outServiceName );
+ *outStatus = theMajorStatus == GSS_S_COMPLETE ?
+ PAPISuccess : PAPIAuthenticationFailure;
+ }
+}
+
+void writeGSSAPIAuthId( gss_ctx_id_t * inContext,
+ gss_buffer_desc * outToken,
+ PAPIStatus * outStatus )
+{
+ /*
+ * We no longer write the ldap authorisation id as LDAP servers
+ * can't agree on the format.
+ * See 6275775
+ */
+ OM_uint32 theMajorStatus;
+ OM_uint32 theMinorStatus;
+ gss_buffer_desc theAuthzIdBuffer;
+ int theConfState;
+
+ *outStatus = PAPIAuthenticationFailure;
+ theAuthzIdBuffer.length = 4;
+ theAuthzIdBuffer.value = malloc( theAuthzIdBuffer.length );
+ if ( theAuthzIdBuffer.value != 0 )
+ {
+ char * theCP = ( char *)theAuthzIdBuffer.value;
+ /* security layer */
+ theCP[ 0 ] = ( char )1;
+ /* message size */
+ theCP[ 1 ] = ( char )1;
+ theCP[ 2 ] = theCP[ 3 ] = ( char )0;
+
+ theMajorStatus = gss_wrap( &theMinorStatus,
+ *inContext,
+ 0,
+ GSS_C_QOP_DEFAULT,
+ &theAuthzIdBuffer,
+ &theConfState,
+ outToken );
+ free( theAuthzIdBuffer.value );
+ if ( theMajorStatus == GSS_S_COMPLETE )
+ {
+ *outStatus = PAPISuccess;
+ }
+ }
+}