pax_global_header00006660000000000000000000000064133264261210014512gustar00rootroot0000000000000052 comment=dbc13845739c28343771c5c282b1e3aea485b23b openvpn-auth-ldap-auth-ldap-2.0.4/000077500000000000000000000000001332642612100167345ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/.gitignore000066400000000000000000000004241332642612100207240ustar00rootroot00000000000000Makefile Mk/autoconf.mk Mk/compile.mk Mk/subdir.mk autom4te.cache/ config.h config.h.in config.log config.status configure docs/Makefile docs/doxyfile src/Makefile tests/Makefile tools/Makefile AuthLDAP.xcodeproj/project.xcworkspace/xcuserdata/ AuthLDAP.xcodeproj/xcuserdata/ openvpn-auth-ldap-auth-ldap-2.0.4/AuthLDAP.xcodeproj/000077500000000000000000000000001332642612100222725ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/AuthLDAP.xcodeproj/project.pbxproj000066400000000000000000001701051332642612100253520ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 055C589F15029D4000B34430 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 055C589E15029D4000B34430 /* Foundation.framework */; }; 05733B7A15DB7372009E53FA /* asprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 05733B7915DB7372009E53FA /* asprintf.c */; }; 05733B7B15DB7372009E53FA /* asprintf.c in Sources */ = {isa = PBXBuildFile; fileRef = 05733B7915DB7372009E53FA /* asprintf.c */; }; 05B374F41502FADC005E3D62 /* auth-ldap.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374BF1502FADC005E3D62 /* auth-ldap.m */; }; 05B374F51502FADC005E3D62 /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 05B374C01502FADC005E3D62 /* hash.c */; }; 05B374F61502FADC005E3D62 /* hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374C11502FADC005E3D62 /* hash.h */; }; 05B374F71502FADC005E3D62 /* PXObjCRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374C31502FADC005E3D62 /* PXObjCRuntime.h */; }; 05B374F81502FADC005E3D62 /* strlcpy.c in Sources */ = {isa = PBXBuildFile; fileRef = 05B374C41502FADC005E3D62 /* strlcpy.c */; }; 05B374F91502FADC005E3D62 /* strlcpy.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374C51502FADC005E3D62 /* strlcpy.h */; }; 05B374FA1502FADC005E3D62 /* testplugin.c in Sources */ = {isa = PBXBuildFile; fileRef = 05B374C61502FADC005E3D62 /* testplugin.c */; }; 05B374FB1502FADC005E3D62 /* TRAccountRepository.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374C71502FADC005E3D62 /* TRAccountRepository.h */; }; 05B374FC1502FADC005E3D62 /* TRArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374C81502FADC005E3D62 /* TRArray.h */; }; 05B374FD1502FADC005E3D62 /* TRArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374C91502FADC005E3D62 /* TRArray.m */; }; 05B374FE1502FADC005E3D62 /* TRAuthLDAPConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374CA1502FADC005E3D62 /* TRAuthLDAPConfig.h */; }; 05B374FF1502FADC005E3D62 /* TRAuthLDAPConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374CB1502FADC005E3D62 /* TRAuthLDAPConfig.m */; }; 05B375001502FADC005E3D62 /* TRAutoreleasePool.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374CC1502FADC005E3D62 /* TRAutoreleasePool.h */; }; 05B375011502FADC005E3D62 /* TRAutoreleasePool.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374CD1502FADC005E3D62 /* TRAutoreleasePool.m */; }; 05B375021502FADC005E3D62 /* TRConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374CE1502FADC005E3D62 /* TRConfig.h */; }; 05B375031502FADC005E3D62 /* TRConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374CF1502FADC005E3D62 /* TRConfig.m */; }; 05B375041502FADC005E3D62 /* TRConfigLexer.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374D01502FADC005E3D62 /* TRConfigLexer.h */; }; 05B375051502FADC005E3D62 /* TRConfigToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374D31502FADC005E3D62 /* TRConfigToken.h */; }; 05B375061502FADC005E3D62 /* TRConfigToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374D41502FADC005E3D62 /* TRConfigToken.m */; }; 05B375071502FADC005E3D62 /* TREnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374D51502FADC005E3D62 /* TREnumerator.h */; }; 05B375081502FADC005E3D62 /* TREnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374D61502FADC005E3D62 /* TREnumerator.m */; }; 05B375091502FADC005E3D62 /* TRHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374D71502FADC005E3D62 /* TRHash.h */; }; 05B3750A1502FADC005E3D62 /* TRHash.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374D81502FADC005E3D62 /* TRHash.m */; }; 05B3750B1502FADC005E3D62 /* TRLDAPAccountRepository.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374D91502FADC005E3D62 /* TRLDAPAccountRepository.h */; }; 05B3750C1502FADC005E3D62 /* TRLDAPAccountRepository.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374DA1502FADC005E3D62 /* TRLDAPAccountRepository.m */; }; 05B3750D1502FADC005E3D62 /* TRLDAPConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374DB1502FADC005E3D62 /* TRLDAPConnection.h */; }; 05B3750E1502FADC005E3D62 /* TRLDAPConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374DC1502FADC005E3D62 /* TRLDAPConnection.m */; }; 05B3750F1502FADC005E3D62 /* TRLDAPEntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374DD1502FADC005E3D62 /* TRLDAPEntry.h */; }; 05B375101502FADC005E3D62 /* TRLDAPEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374DE1502FADC005E3D62 /* TRLDAPEntry.m */; }; 05B375111502FADC005E3D62 /* TRLDAPGroupConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374DF1502FADC005E3D62 /* TRLDAPGroupConfig.h */; }; 05B375121502FADC005E3D62 /* TRLDAPGroupConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374E01502FADC005E3D62 /* TRLDAPGroupConfig.m */; }; 05B375131502FADC005E3D62 /* TRLDAPSearchFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374E11502FADC005E3D62 /* TRLDAPSearchFilter.h */; }; 05B375141502FADC005E3D62 /* TRLDAPSearchFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374E21502FADC005E3D62 /* TRLDAPSearchFilter.m */; }; 05B375151502FADC005E3D62 /* TRLocalPacketFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374E31502FADC005E3D62 /* TRLocalPacketFilter.h */; }; 05B375161502FADC005E3D62 /* TRLocalPacketFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374E41502FADC005E3D62 /* TRLocalPacketFilter.m */; }; 05B375171502FADC005E3D62 /* TRLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374E51502FADC005E3D62 /* TRLog.h */; }; 05B375181502FADC005E3D62 /* TRLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374E61502FADC005E3D62 /* TRLog.m */; }; 05B375191502FADC005E3D62 /* TRObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374E71502FADC005E3D62 /* TRObject.h */; }; 05B3751A1502FADC005E3D62 /* TRObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374E81502FADC005E3D62 /* TRObject.m */; }; 05B3751B1502FADC005E3D62 /* TRPacketFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374E91502FADC005E3D62 /* TRPacketFilter.h */; }; 05B3751C1502FADC005E3D62 /* TRPacketFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374EA1502FADC005E3D62 /* TRPacketFilter.m */; }; 05B3751D1502FADC005E3D62 /* TRPFAddress.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374EB1502FADC005E3D62 /* TRPFAddress.h */; }; 05B3751E1502FADC005E3D62 /* TRPFAddress.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374EC1502FADC005E3D62 /* TRPFAddress.m */; }; 05B3751F1502FADC005E3D62 /* TRString.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374ED1502FADC005E3D62 /* TRString.h */; }; 05B375201502FADC005E3D62 /* TRString.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374EE1502FADC005E3D62 /* TRString.m */; }; 05B375211502FADC005E3D62 /* TRVPNPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374EF1502FADC005E3D62 /* TRVPNPlugin.h */; }; 05B375221502FADC005E3D62 /* TRVPNSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374F01502FADC005E3D62 /* TRVPNSession.h */; }; 05B375231502FADC005E3D62 /* TRVPNSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B374F11502FADC005E3D62 /* TRVPNSession.m */; }; 05B375241502FADC005E3D62 /* xmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 05B374F21502FADC005E3D62 /* xmalloc.c */; }; 05B375251502FADC005E3D62 /* xmalloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B374F31502FADC005E3D62 /* xmalloc.h */; }; 05B375301502FBE9005E3D62 /* openvpn-plugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 05B3752F1502FBE9005E3D62 /* openvpn-plugin.h */; }; 05B375481502FC88005E3D62 /* lemon.c in Sources */ = {isa = PBXBuildFile; fileRef = 05B375411502FC3F005E3D62 /* lemon.c */; }; 05B3755715031709005E3D62 /* makeheaders.c in Sources */ = {isa = PBXBuildFile; fileRef = 05B375441502FC3F005E3D62 /* makeheaders.c */; }; 05B3758115031864005E3D62 /* TRConfigParser.lemon in Sources */ = {isa = PBXBuildFile; fileRef = 05B374D21502FADC005E3D62 /* TRConfigParser.lemon */; }; 05B375B615031DE5005E3D62 /* mockpf.c in Sources */ = {isa = PBXBuildFile; fileRef = 05B3759515031DE5005E3D62 /* mockpf.c */; }; 05B375B715031DE5005E3D62 /* PXTestAssert.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B3759815031DE5005E3D62 /* PXTestAssert.m */; }; 05B375B815031DE5005E3D62 /* PXTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B3759A15031DE5005E3D62 /* PXTestCase.m */; }; 05B375B915031DE5005E3D62 /* PXTestCaseRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B3759C15031DE5005E3D62 /* PXTestCaseRunner.m */; }; 05B375BA15031DE5005E3D62 /* PXTestConsoleResultHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B3759E15031DE5005E3D62 /* PXTestConsoleResultHandler.m */; }; 05B375BB15031DE5005E3D62 /* PXTestException.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375A015031DE5005E3D62 /* PXTestException.m */; }; 05B375BC15031DE5005E3D62 /* tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375A415031DE5005E3D62 /* tests.m */; }; 05B375BD15031DE5005E3D62 /* TRArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375A515031DE5005E3D62 /* TRArrayTests.m */; }; 05B375BE15031DE5005E3D62 /* TRAuthLDAPConfigTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375A615031DE5005E3D62 /* TRAuthLDAPConfigTests.m */; }; 05B375BF15031DE5005E3D62 /* TRAutoreleasePoolTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375A715031DE5005E3D62 /* TRAutoreleasePoolTests.m */; }; 05B375C015031DE5005E3D62 /* TRConfigLexerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375A815031DE5005E3D62 /* TRConfigLexerTests.m */; }; 05B375C115031DE5005E3D62 /* TRConfigTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375A915031DE5005E3D62 /* TRConfigTests.m */; }; 05B375C215031DE5005E3D62 /* TRConfigTokenTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375AA15031DE5005E3D62 /* TRConfigTokenTests.m */; }; 05B375C315031DE5005E3D62 /* TRHashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375AB15031DE5005E3D62 /* TRHashTests.m */; }; 05B375C415031DE5005E3D62 /* TRLDAPAccountRepositoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375AC15031DE5005E3D62 /* TRLDAPAccountRepositoryTests.m */; }; 05B375C515031DE5005E3D62 /* TRLDAPConnectionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375AD15031DE5005E3D62 /* TRLDAPConnectionTests.m */; }; 05B375C615031DE5005E3D62 /* TRLDAPEntryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375AE15031DE5005E3D62 /* TRLDAPEntryTests.m */; }; 05B375C715031DE5005E3D62 /* TRLDAPGroupConfigTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375AF15031DE5005E3D62 /* TRLDAPGroupConfigTests.m */; }; 05B375C815031DE5005E3D62 /* TRLDAPSearchFilterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375B015031DE5005E3D62 /* TRLDAPSearchFilterTests.m */; }; 05B375C915031DE5005E3D62 /* TRLocalPacketFilterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375B115031DE5005E3D62 /* TRLocalPacketFilterTests.m */; }; 05B375CA15031DE5005E3D62 /* TRObjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375B215031DE5005E3D62 /* TRObjectTests.m */; }; 05B375CB15031DE5005E3D62 /* TRPFAddressTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375B315031DE5005E3D62 /* TRPFAddressTests.m */; }; 05B375CC15031DE5005E3D62 /* TRStringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375B415031DE5005E3D62 /* TRStringTests.m */; }; 05B375CD15031DE5005E3D62 /* TRVPNSessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 05B375B515031DE5005E3D62 /* TRVPNSessionTests.m */; }; 05B375D515032AE5005E3D62 /* libauthldap.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 055C58B515029D9F00B34430 /* libauthldap.a */; }; 05B375D715032AFC005E3D62 /* libldap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 05B375D615032AFC005E3D62 /* libldap.dylib */; }; 05B375D815032B20005E3D62 /* TRConfigLexer.re in Sources */ = {isa = PBXBuildFile; fileRef = 05B374D11502FADC005E3D62 /* TRConfigLexer.re */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ 05B3755C1503173C005E3D62 /* PBXBuildRule */ = { isa = PBXBuildRule; compilerSpec = com.apple.compilers.proxy.script; filePatterns = "*.lemon"; fileType = pattern.proxy; isEditable = 1; outputFiles = ( "${SHARED_DERIVED_FILE_DIR}/${CURRENT_ARCH}/${INPUT_FILE_BASE}.m", "${SHARED_DERIVED_FILE_DIR}/${CURRENT_ARCH}/${INPUT_FILE_BASE}.h", ); script = "\"${BUILT_PRODUCTS_DIR}/lemon\" -T${SRCROOT}/tools/lempar.c -m -q \"${INPUT_FILE_PATH}\" \"-O${SHARED_DERIVED_FILE_DIR}/${CURRENT_ARCH}/${INPUT_FILE_BASE}.m\"\n\n\"${BUILT_PRODUCTS_DIR}/makeheaders\" \"${SHARED_DERIVED_FILE_DIR}/${CURRENT_ARCH}/${INPUT_FILE_BASE}.m\"\n\n\n\n"; }; 05B375D915032B24005E3D62 /* PBXBuildRule */ = { isa = PBXBuildRule; compilerSpec = com.apple.compilers.proxy.script; filePatterns = "*.re"; fileType = pattern.proxy; isEditable = 1; outputFiles = ( "${SHARED_DERIVED_FILE_DIR}/${CURRENT_ARCH}/${INPUT_FILE_BASE}.m", ); script = "# Add additional search locations for re2c\nexport PATH=\"${PATH}:/opt/local/bin:/usr/local/bin\"\n\nre2c -o \"${SHARED_DERIVED_FILE_DIR}/${CURRENT_ARCH}/${INPUT_FILE_BASE}.m\" \"${INPUT_FILE_PATH}\""; }; /* End PBXBuildRule section */ /* Begin PBXContainerItemProxy section */ 05B3755815031716005E3D62 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 055C589115029D4000B34430 /* Project object */; proxyType = 1; remoteGlobalIDString = 05B375351502FC2F005E3D62; remoteInfo = lemon; }; 05B3755A15031717005E3D62 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 055C589115029D4000B34430 /* Project object */; proxyType = 1; remoteGlobalIDString = 05B3754C150316FD005E3D62; remoteInfo = makeheaders; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ 055C589815029D4000B34430 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); runOnlyForDeploymentPostprocessing = 1; }; 05B375341502FC2F005E3D62 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); runOnlyForDeploymentPostprocessing = 1; }; 05B3754B150316FD005E3D62 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); runOnlyForDeploymentPostprocessing = 1; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 055C589A15029D4000B34430 /* tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tests; sourceTree = BUILT_PRODUCTS_DIR; }; 055C589E15029D4000B34430 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 055C58B515029D9F00B34430 /* libauthldap.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libauthldap.a; sourceTree = BUILT_PRODUCTS_DIR; }; 05733B7915DB7372009E53FA /* asprintf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = asprintf.c; sourceTree = ""; }; 05B374BF1502FADC005E3D62 /* auth-ldap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "auth-ldap.m"; sourceTree = ""; }; 05B374C01502FADC005E3D62 /* hash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hash.c; sourceTree = ""; }; 05B374C11502FADC005E3D62 /* hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hash.h; sourceTree = ""; }; 05B374C21502FADC005E3D62 /* Makefile.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; 05B374C31502FADC005E3D62 /* PXObjCRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PXObjCRuntime.h; sourceTree = ""; }; 05B374C41502FADC005E3D62 /* strlcpy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = strlcpy.c; sourceTree = ""; }; 05B374C51502FADC005E3D62 /* strlcpy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = strlcpy.h; sourceTree = ""; }; 05B374C61502FADC005E3D62 /* testplugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testplugin.c; sourceTree = ""; }; 05B374C71502FADC005E3D62 /* TRAccountRepository.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRAccountRepository.h; sourceTree = ""; }; 05B374C81502FADC005E3D62 /* TRArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRArray.h; sourceTree = ""; }; 05B374C91502FADC005E3D62 /* TRArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRArray.m; sourceTree = ""; }; 05B374CA1502FADC005E3D62 /* TRAuthLDAPConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRAuthLDAPConfig.h; sourceTree = ""; }; 05B374CB1502FADC005E3D62 /* TRAuthLDAPConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRAuthLDAPConfig.m; sourceTree = ""; }; 05B374CC1502FADC005E3D62 /* TRAutoreleasePool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRAutoreleasePool.h; sourceTree = ""; }; 05B374CD1502FADC005E3D62 /* TRAutoreleasePool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRAutoreleasePool.m; sourceTree = ""; }; 05B374CE1502FADC005E3D62 /* TRConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRConfig.h; sourceTree = ""; }; 05B374CF1502FADC005E3D62 /* TRConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRConfig.m; sourceTree = ""; }; 05B374D01502FADC005E3D62 /* TRConfigLexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRConfigLexer.h; sourceTree = ""; }; 05B374D11502FADC005E3D62 /* TRConfigLexer.re */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TRConfigLexer.re; sourceTree = ""; }; 05B374D21502FADC005E3D62 /* TRConfigParser.lemon */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TRConfigParser.lemon; sourceTree = ""; }; 05B374D31502FADC005E3D62 /* TRConfigToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRConfigToken.h; sourceTree = ""; }; 05B374D41502FADC005E3D62 /* TRConfigToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRConfigToken.m; sourceTree = ""; }; 05B374D51502FADC005E3D62 /* TREnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TREnumerator.h; sourceTree = ""; }; 05B374D61502FADC005E3D62 /* TREnumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TREnumerator.m; sourceTree = ""; }; 05B374D71502FADC005E3D62 /* TRHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRHash.h; sourceTree = ""; }; 05B374D81502FADC005E3D62 /* TRHash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRHash.m; sourceTree = ""; }; 05B374D91502FADC005E3D62 /* TRLDAPAccountRepository.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRLDAPAccountRepository.h; sourceTree = ""; }; 05B374DA1502FADC005E3D62 /* TRLDAPAccountRepository.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLDAPAccountRepository.m; sourceTree = ""; }; 05B374DB1502FADC005E3D62 /* TRLDAPConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRLDAPConnection.h; sourceTree = ""; }; 05B374DC1502FADC005E3D62 /* TRLDAPConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLDAPConnection.m; sourceTree = ""; }; 05B374DD1502FADC005E3D62 /* TRLDAPEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRLDAPEntry.h; sourceTree = ""; }; 05B374DE1502FADC005E3D62 /* TRLDAPEntry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLDAPEntry.m; sourceTree = ""; }; 05B374DF1502FADC005E3D62 /* TRLDAPGroupConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRLDAPGroupConfig.h; sourceTree = ""; }; 05B374E01502FADC005E3D62 /* TRLDAPGroupConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLDAPGroupConfig.m; sourceTree = ""; }; 05B374E11502FADC005E3D62 /* TRLDAPSearchFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRLDAPSearchFilter.h; sourceTree = ""; }; 05B374E21502FADC005E3D62 /* TRLDAPSearchFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLDAPSearchFilter.m; sourceTree = ""; }; 05B374E31502FADC005E3D62 /* TRLocalPacketFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRLocalPacketFilter.h; sourceTree = ""; }; 05B374E41502FADC005E3D62 /* TRLocalPacketFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLocalPacketFilter.m; sourceTree = ""; }; 05B374E51502FADC005E3D62 /* TRLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRLog.h; sourceTree = ""; }; 05B374E61502FADC005E3D62 /* TRLog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLog.m; sourceTree = ""; }; 05B374E71502FADC005E3D62 /* TRObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRObject.h; sourceTree = ""; }; 05B374E81502FADC005E3D62 /* TRObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRObject.m; sourceTree = ""; }; 05B374E91502FADC005E3D62 /* TRPacketFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRPacketFilter.h; sourceTree = ""; }; 05B374EA1502FADC005E3D62 /* TRPacketFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRPacketFilter.m; sourceTree = ""; }; 05B374EB1502FADC005E3D62 /* TRPFAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRPFAddress.h; sourceTree = ""; }; 05B374EC1502FADC005E3D62 /* TRPFAddress.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRPFAddress.m; sourceTree = ""; }; 05B374ED1502FADC005E3D62 /* TRString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRString.h; sourceTree = ""; }; 05B374EE1502FADC005E3D62 /* TRString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRString.m; sourceTree = ""; }; 05B374EF1502FADC005E3D62 /* TRVPNPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRVPNPlugin.h; sourceTree = ""; }; 05B374F01502FADC005E3D62 /* TRVPNSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRVPNSession.h; sourceTree = ""; }; 05B374F11502FADC005E3D62 /* TRVPNSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRVPNSession.m; sourceTree = ""; }; 05B374F21502FADC005E3D62 /* xmalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xmalloc.c; sourceTree = ""; }; 05B374F31502FADC005E3D62 /* xmalloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xmalloc.h; sourceTree = ""; }; 05B3752F1502FBE9005E3D62 /* openvpn-plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "openvpn-plugin.h"; sourceTree = ""; }; 05B375361502FC2F005E3D62 /* lemon */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lemon; sourceTree = BUILT_PRODUCTS_DIR; }; 05B375411502FC3F005E3D62 /* lemon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lemon.c; sourceTree = ""; }; 05B375421502FC3F005E3D62 /* lempar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lempar.c; sourceTree = ""; }; 05B375431502FC3F005E3D62 /* Makefile.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; 05B375441502FC3F005E3D62 /* makeheaders.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = makeheaders.c; sourceTree = ""; }; 05B375451502FC3F005E3D62 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; 05B3754D150316FD005E3D62 /* makeheaders */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = makeheaders; sourceTree = BUILT_PRODUCTS_DIR; }; 05B3758A15031DE5005E3D62 /* auth-ldap-bad-section.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "auth-ldap-bad-section.conf"; sourceTree = ""; }; 05B3758B15031DE5005E3D62 /* auth-ldap-mismatched.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "auth-ldap-mismatched.conf"; sourceTree = ""; }; 05B3758C15031DE5005E3D62 /* auth-ldap-missing-newline.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "auth-ldap-missing-newline.conf"; sourceTree = ""; }; 05B3758D15031DE5005E3D62 /* auth-ldap-multikey.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "auth-ldap-multikey.conf"; sourceTree = ""; }; 05B3758E15031DE5005E3D62 /* auth-ldap-named.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "auth-ldap-named.conf"; sourceTree = ""; }; 05B3758F15031DE5005E3D62 /* auth-ldap-pf.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "auth-ldap-pf.conf"; sourceTree = ""; }; 05B3759015031DE5005E3D62 /* auth-ldap-required.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "auth-ldap-required.conf"; sourceTree = ""; }; 05B3759115031DE5005E3D62 /* auth-ldap.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "auth-ldap.conf"; sourceTree = ""; }; 05B3759215031DE5005E3D62 /* test-lineNumbers.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "test-lineNumbers.conf"; sourceTree = ""; }; 05B3759315031DE5005E3D62 /* TRConfig.conf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TRConfig.conf; sourceTree = ""; }; 05B3759415031DE5005E3D62 /* Makefile.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.in; sourceTree = ""; }; 05B3759515031DE5005E3D62 /* mockpf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mockpf.c; sourceTree = ""; }; 05B3759615031DE5005E3D62 /* mockpf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mockpf.h; sourceTree = ""; }; 05B3759715031DE5005E3D62 /* PXTestAssert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PXTestAssert.h; sourceTree = ""; }; 05B3759815031DE5005E3D62 /* PXTestAssert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PXTestAssert.m; sourceTree = ""; }; 05B3759915031DE5005E3D62 /* PXTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PXTestCase.h; sourceTree = ""; }; 05B3759A15031DE5005E3D62 /* PXTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PXTestCase.m; sourceTree = ""; }; 05B3759B15031DE5005E3D62 /* PXTestCaseRunner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PXTestCaseRunner.h; sourceTree = ""; }; 05B3759C15031DE5005E3D62 /* PXTestCaseRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PXTestCaseRunner.m; sourceTree = ""; }; 05B3759D15031DE5005E3D62 /* PXTestConsoleResultHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PXTestConsoleResultHandler.h; sourceTree = ""; }; 05B3759E15031DE5005E3D62 /* PXTestConsoleResultHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PXTestConsoleResultHandler.m; sourceTree = ""; }; 05B3759F15031DE5005E3D62 /* PXTestException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PXTestException.h; sourceTree = ""; }; 05B375A015031DE5005E3D62 /* PXTestException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PXTestException.m; sourceTree = ""; }; 05B375A115031DE5005E3D62 /* PXTestObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PXTestObjC.h; sourceTree = ""; }; 05B375A215031DE5005E3D62 /* PXTestResultHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PXTestResultHandler.h; sourceTree = ""; }; 05B375A315031DE5005E3D62 /* tests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tests.h; sourceTree = ""; }; 05B375A415031DE5005E3D62 /* tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = tests.m; sourceTree = ""; }; 05B375A515031DE5005E3D62 /* TRArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRArrayTests.m; sourceTree = ""; }; 05B375A615031DE5005E3D62 /* TRAuthLDAPConfigTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRAuthLDAPConfigTests.m; sourceTree = ""; }; 05B375A715031DE5005E3D62 /* TRAutoreleasePoolTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRAutoreleasePoolTests.m; sourceTree = ""; }; 05B375A815031DE5005E3D62 /* TRConfigLexerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRConfigLexerTests.m; sourceTree = ""; }; 05B375A915031DE5005E3D62 /* TRConfigTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRConfigTests.m; sourceTree = ""; }; 05B375AA15031DE5005E3D62 /* TRConfigTokenTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRConfigTokenTests.m; sourceTree = ""; }; 05B375AB15031DE5005E3D62 /* TRHashTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRHashTests.m; sourceTree = ""; }; 05B375AC15031DE5005E3D62 /* TRLDAPAccountRepositoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLDAPAccountRepositoryTests.m; sourceTree = ""; }; 05B375AD15031DE5005E3D62 /* TRLDAPConnectionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLDAPConnectionTests.m; sourceTree = ""; }; 05B375AE15031DE5005E3D62 /* TRLDAPEntryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLDAPEntryTests.m; sourceTree = ""; }; 05B375AF15031DE5005E3D62 /* TRLDAPGroupConfigTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLDAPGroupConfigTests.m; sourceTree = ""; }; 05B375B015031DE5005E3D62 /* TRLDAPSearchFilterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLDAPSearchFilterTests.m; sourceTree = ""; }; 05B375B115031DE5005E3D62 /* TRLocalPacketFilterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRLocalPacketFilterTests.m; sourceTree = ""; }; 05B375B215031DE5005E3D62 /* TRObjectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRObjectTests.m; sourceTree = ""; }; 05B375B315031DE5005E3D62 /* TRPFAddressTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRPFAddressTests.m; sourceTree = ""; }; 05B375B415031DE5005E3D62 /* TRStringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRStringTests.m; sourceTree = ""; }; 05B375B515031DE5005E3D62 /* TRVPNSessionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRVPNSessionTests.m; sourceTree = ""; }; 05B375D615032AFC005E3D62 /* libldap.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libldap.dylib; path = usr/lib/libldap.dylib; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 055C589715029D4000B34430 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 05B375D715032AFC005E3D62 /* libldap.dylib in Frameworks */, 055C589F15029D4000B34430 /* Foundation.framework in Frameworks */, 05B375D515032AE5005E3D62 /* libauthldap.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 055C58B215029D9F00B34430 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 05B375331502FC2F005E3D62 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 05B3754A150316FD005E3D62 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 055C588F15029D4000B34430 = { isa = PBXGroup; children = ( 05B375401502FC3F005E3D62 /* tools */, 05B374BE1502FADC005E3D62 /* src */, 05B3758815031DE5005E3D62 /* tests */, 055C589D15029D4000B34430 /* Frameworks */, 055C589B15029D4000B34430 /* Products */, ); sourceTree = ""; }; 055C589B15029D4000B34430 /* Products */ = { isa = PBXGroup; children = ( 055C589A15029D4000B34430 /* tests */, 055C58B515029D9F00B34430 /* libauthldap.a */, 05B375361502FC2F005E3D62 /* lemon */, 05B3754D150316FD005E3D62 /* makeheaders */, ); name = Products; sourceTree = ""; }; 055C589D15029D4000B34430 /* Frameworks */ = { isa = PBXGroup; children = ( 05B3752F1502FBE9005E3D62 /* openvpn-plugin.h */, 05B375D615032AFC005E3D62 /* libldap.dylib */, 055C589E15029D4000B34430 /* Foundation.framework */, ); name = Frameworks; sourceTree = ""; }; 05B374BE1502FADC005E3D62 /* src */ = { isa = PBXGroup; children = ( 05B374C21502FADC005E3D62 /* Makefile.in */, 05B374BF1502FADC005E3D62 /* auth-ldap.m */, 05B374C61502FADC005E3D62 /* testplugin.c */, 05B3752C1502FB3A005E3D62 /* VPN */, 05B375271502FAF2005E3D62 /* Config */, 05B375281502FB0D005E3D62 /* Foundation */, 05B375291502FB18005E3D62 /* LDAP */, 05B3752B1502FB31005E3D62 /* PF */, 05B3752A1502FB25005E3D62 /* Logging */, ); path = src; sourceTree = ""; }; 05B375271502FAF2005E3D62 /* Config */ = { isa = PBXGroup; children = ( 05B374CA1502FADC005E3D62 /* TRAuthLDAPConfig.h */, 05B374CB1502FADC005E3D62 /* TRAuthLDAPConfig.m */, 05B374CE1502FADC005E3D62 /* TRConfig.h */, 05B374CF1502FADC005E3D62 /* TRConfig.m */, 05B374D01502FADC005E3D62 /* TRConfigLexer.h */, 05B374D11502FADC005E3D62 /* TRConfigLexer.re */, 05B374D21502FADC005E3D62 /* TRConfigParser.lemon */, 05B374D31502FADC005E3D62 /* TRConfigToken.h */, 05B374D41502FADC005E3D62 /* TRConfigToken.m */, 05B374DF1502FADC005E3D62 /* TRLDAPGroupConfig.h */, 05B374E01502FADC005E3D62 /* TRLDAPGroupConfig.m */, ); name = Config; sourceTree = ""; }; 05B375281502FB0D005E3D62 /* Foundation */ = { isa = PBXGroup; children = ( 05B374C01502FADC005E3D62 /* hash.c */, 05B374C11502FADC005E3D62 /* hash.h */, 05B374C31502FADC005E3D62 /* PXObjCRuntime.h */, 05B374C41502FADC005E3D62 /* strlcpy.c */, 05B374C51502FADC005E3D62 /* strlcpy.h */, 05B374C81502FADC005E3D62 /* TRArray.h */, 05B374C91502FADC005E3D62 /* TRArray.m */, 05B374CC1502FADC005E3D62 /* TRAutoreleasePool.h */, 05B374CD1502FADC005E3D62 /* TRAutoreleasePool.m */, 05B374D51502FADC005E3D62 /* TREnumerator.h */, 05B374D61502FADC005E3D62 /* TREnumerator.m */, 05B374D71502FADC005E3D62 /* TRHash.h */, 05B374D81502FADC005E3D62 /* TRHash.m */, 05B374E71502FADC005E3D62 /* TRObject.h */, 05B374E81502FADC005E3D62 /* TRObject.m */, 05B374ED1502FADC005E3D62 /* TRString.h */, 05B374EE1502FADC005E3D62 /* TRString.m */, 05B374F21502FADC005E3D62 /* xmalloc.c */, 05B374F31502FADC005E3D62 /* xmalloc.h */, 05733B7915DB7372009E53FA /* asprintf.c */, ); name = Foundation; sourceTree = ""; }; 05B375291502FB18005E3D62 /* LDAP */ = { isa = PBXGroup; children = ( 05B374D91502FADC005E3D62 /* TRLDAPAccountRepository.h */, 05B374DA1502FADC005E3D62 /* TRLDAPAccountRepository.m */, 05B374DB1502FADC005E3D62 /* TRLDAPConnection.h */, 05B374DC1502FADC005E3D62 /* TRLDAPConnection.m */, 05B374DD1502FADC005E3D62 /* TRLDAPEntry.h */, 05B374DE1502FADC005E3D62 /* TRLDAPEntry.m */, 05B374E11502FADC005E3D62 /* TRLDAPSearchFilter.h */, 05B374E21502FADC005E3D62 /* TRLDAPSearchFilter.m */, ); name = LDAP; sourceTree = ""; }; 05B3752A1502FB25005E3D62 /* Logging */ = { isa = PBXGroup; children = ( 05B374E51502FADC005E3D62 /* TRLog.h */, 05B374E61502FADC005E3D62 /* TRLog.m */, ); name = Logging; sourceTree = ""; }; 05B3752B1502FB31005E3D62 /* PF */ = { isa = PBXGroup; children = ( 05B374E31502FADC005E3D62 /* TRLocalPacketFilter.h */, 05B374E41502FADC005E3D62 /* TRLocalPacketFilter.m */, 05B374E91502FADC005E3D62 /* TRPacketFilter.h */, 05B374EA1502FADC005E3D62 /* TRPacketFilter.m */, 05B374EB1502FADC005E3D62 /* TRPFAddress.h */, 05B374EC1502FADC005E3D62 /* TRPFAddress.m */, ); name = PF; sourceTree = ""; }; 05B3752C1502FB3A005E3D62 /* VPN */ = { isa = PBXGroup; children = ( 05B374C71502FADC005E3D62 /* TRAccountRepository.h */, 05B374EF1502FADC005E3D62 /* TRVPNPlugin.h */, 05B374F01502FADC005E3D62 /* TRVPNSession.h */, 05B374F11502FADC005E3D62 /* TRVPNSession.m */, ); name = VPN; sourceTree = ""; }; 05B375401502FC3F005E3D62 /* tools */ = { isa = PBXGroup; children = ( 05B375411502FC3F005E3D62 /* lemon.c */, 05B375421502FC3F005E3D62 /* lempar.c */, 05B375431502FC3F005E3D62 /* Makefile.in */, 05B375441502FC3F005E3D62 /* makeheaders.c */, 05B375451502FC3F005E3D62 /* README */, ); path = tools; sourceTree = ""; }; 05B3758815031DE5005E3D62 /* tests */ = { isa = PBXGroup; children = ( 05B3759415031DE5005E3D62 /* Makefile.in */, 05B375A315031DE5005E3D62 /* tests.h */, 05B375A415031DE5005E3D62 /* tests.m */, 05B3758915031DE5005E3D62 /* data */, 05B375D015031E88005E3D62 /* PF */, 05B375CF15031E6E005E3D62 /* Test Runner */, 05B375D115031E95005E3D62 /* Foundation */, 05B375D415031EC4005E3D62 /* Config */, 05B375D315031EBD005E3D62 /* LDAP */, 05B375D215031EAC005E3D62 /* VPN */, ); path = tests; sourceTree = ""; }; 05B3758915031DE5005E3D62 /* data */ = { isa = PBXGroup; children = ( 05B3758A15031DE5005E3D62 /* auth-ldap-bad-section.conf */, 05B3758B15031DE5005E3D62 /* auth-ldap-mismatched.conf */, 05B3758C15031DE5005E3D62 /* auth-ldap-missing-newline.conf */, 05B3758D15031DE5005E3D62 /* auth-ldap-multikey.conf */, 05B3758E15031DE5005E3D62 /* auth-ldap-named.conf */, 05B3758F15031DE5005E3D62 /* auth-ldap-pf.conf */, 05B3759015031DE5005E3D62 /* auth-ldap-required.conf */, 05B3759115031DE5005E3D62 /* auth-ldap.conf */, 05B3759215031DE5005E3D62 /* test-lineNumbers.conf */, 05B3759315031DE5005E3D62 /* TRConfig.conf */, ); path = data; sourceTree = ""; }; 05B375CF15031E6E005E3D62 /* Test Runner */ = { isa = PBXGroup; children = ( 05B3759715031DE5005E3D62 /* PXTestAssert.h */, 05B3759815031DE5005E3D62 /* PXTestAssert.m */, 05B3759915031DE5005E3D62 /* PXTestCase.h */, 05B3759A15031DE5005E3D62 /* PXTestCase.m */, 05B3759B15031DE5005E3D62 /* PXTestCaseRunner.h */, 05B3759C15031DE5005E3D62 /* PXTestCaseRunner.m */, 05B3759D15031DE5005E3D62 /* PXTestConsoleResultHandler.h */, 05B3759E15031DE5005E3D62 /* PXTestConsoleResultHandler.m */, 05B3759F15031DE5005E3D62 /* PXTestException.h */, 05B375A015031DE5005E3D62 /* PXTestException.m */, 05B375A115031DE5005E3D62 /* PXTestObjC.h */, 05B375A215031DE5005E3D62 /* PXTestResultHandler.h */, ); name = "Test Runner"; sourceTree = ""; }; 05B375D015031E88005E3D62 /* PF */ = { isa = PBXGroup; children = ( 05B3759515031DE5005E3D62 /* mockpf.c */, 05B3759615031DE5005E3D62 /* mockpf.h */, 05B375B115031DE5005E3D62 /* TRLocalPacketFilterTests.m */, 05B375B315031DE5005E3D62 /* TRPFAddressTests.m */, ); name = PF; sourceTree = ""; }; 05B375D115031E95005E3D62 /* Foundation */ = { isa = PBXGroup; children = ( 05B375A515031DE5005E3D62 /* TRArrayTests.m */, 05B375A715031DE5005E3D62 /* TRAutoreleasePoolTests.m */, 05B375AB15031DE5005E3D62 /* TRHashTests.m */, 05B375B215031DE5005E3D62 /* TRObjectTests.m */, 05B375B415031DE5005E3D62 /* TRStringTests.m */, ); name = Foundation; sourceTree = ""; }; 05B375D215031EAC005E3D62 /* VPN */ = { isa = PBXGroup; children = ( 05B375B515031DE5005E3D62 /* TRVPNSessionTests.m */, ); name = VPN; sourceTree = ""; }; 05B375D315031EBD005E3D62 /* LDAP */ = { isa = PBXGroup; children = ( 05B375AC15031DE5005E3D62 /* TRLDAPAccountRepositoryTests.m */, 05B375AD15031DE5005E3D62 /* TRLDAPConnectionTests.m */, 05B375AE15031DE5005E3D62 /* TRLDAPEntryTests.m */, 05B375B015031DE5005E3D62 /* TRLDAPSearchFilterTests.m */, ); name = LDAP; sourceTree = ""; }; 05B375D415031EC4005E3D62 /* Config */ = { isa = PBXGroup; children = ( 05B375A615031DE5005E3D62 /* TRAuthLDAPConfigTests.m */, 05B375A815031DE5005E3D62 /* TRConfigLexerTests.m */, 05B375A915031DE5005E3D62 /* TRConfigTests.m */, 05B375AA15031DE5005E3D62 /* TRConfigTokenTests.m */, 05B375AF15031DE5005E3D62 /* TRLDAPGroupConfigTests.m */, ); name = Config; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 055C58B315029D9F00B34430 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 05B374F61502FADC005E3D62 /* hash.h in Headers */, 05B374F71502FADC005E3D62 /* PXObjCRuntime.h in Headers */, 05B374F91502FADC005E3D62 /* strlcpy.h in Headers */, 05B374FB1502FADC005E3D62 /* TRAccountRepository.h in Headers */, 05B374FC1502FADC005E3D62 /* TRArray.h in Headers */, 05B374FE1502FADC005E3D62 /* TRAuthLDAPConfig.h in Headers */, 05B375001502FADC005E3D62 /* TRAutoreleasePool.h in Headers */, 05B375021502FADC005E3D62 /* TRConfig.h in Headers */, 05B375041502FADC005E3D62 /* TRConfigLexer.h in Headers */, 05B375051502FADC005E3D62 /* TRConfigToken.h in Headers */, 05B375071502FADC005E3D62 /* TREnumerator.h in Headers */, 05B375091502FADC005E3D62 /* TRHash.h in Headers */, 05B3750B1502FADC005E3D62 /* TRLDAPAccountRepository.h in Headers */, 05B3750D1502FADC005E3D62 /* TRLDAPConnection.h in Headers */, 05B3750F1502FADC005E3D62 /* TRLDAPEntry.h in Headers */, 05B375111502FADC005E3D62 /* TRLDAPGroupConfig.h in Headers */, 05B375131502FADC005E3D62 /* TRLDAPSearchFilter.h in Headers */, 05B375151502FADC005E3D62 /* TRLocalPacketFilter.h in Headers */, 05B375171502FADC005E3D62 /* TRLog.h in Headers */, 05B375191502FADC005E3D62 /* TRObject.h in Headers */, 05B3751B1502FADC005E3D62 /* TRPacketFilter.h in Headers */, 05B3751D1502FADC005E3D62 /* TRPFAddress.h in Headers */, 05B3751F1502FADC005E3D62 /* TRString.h in Headers */, 05B375211502FADC005E3D62 /* TRVPNPlugin.h in Headers */, 05B375221502FADC005E3D62 /* TRVPNSession.h in Headers */, 05B375251502FADC005E3D62 /* xmalloc.h in Headers */, 05B375301502FBE9005E3D62 /* openvpn-plugin.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 055C589915029D4000B34430 /* tests */ = { isa = PBXNativeTarget; buildConfigurationList = 055C58A915029D4000B34430 /* Build configuration list for PBXNativeTarget "tests" */; buildPhases = ( 055C589615029D4000B34430 /* Sources */, 055C589715029D4000B34430 /* Frameworks */, 055C589815029D4000B34430 /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = tests; productName = AuthLDAP; productReference = 055C589A15029D4000B34430 /* tests */; productType = "com.apple.product-type.tool"; }; 055C58B415029D9F00B34430 /* authldap */ = { isa = PBXNativeTarget; buildConfigurationList = 055C58B615029DA000B34430 /* Build configuration list for PBXNativeTarget "authldap" */; buildPhases = ( 055C58B115029D9F00B34430 /* Sources */, 055C58B215029D9F00B34430 /* Frameworks */, 055C58B315029D9F00B34430 /* Headers */, ); buildRules = ( 05B375D915032B24005E3D62 /* PBXBuildRule */, 05B3755C1503173C005E3D62 /* PBXBuildRule */, ); dependencies = ( 05B3755915031716005E3D62 /* PBXTargetDependency */, 05B3755B15031717005E3D62 /* PBXTargetDependency */, ); name = authldap; productName = authldap; productReference = 055C58B515029D9F00B34430 /* libauthldap.a */; productType = "com.apple.product-type.library.static"; }; 05B375351502FC2F005E3D62 /* lemon */ = { isa = PBXNativeTarget; buildConfigurationList = 05B3753D1502FC2F005E3D62 /* Build configuration list for PBXNativeTarget "lemon" */; buildPhases = ( 05B375321502FC2F005E3D62 /* Sources */, 05B375331502FC2F005E3D62 /* Frameworks */, 05B375341502FC2F005E3D62 /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = lemon; productName = lemon; productReference = 05B375361502FC2F005E3D62 /* lemon */; productType = "com.apple.product-type.tool"; }; 05B3754C150316FD005E3D62 /* makeheaders */ = { isa = PBXNativeTarget; buildConfigurationList = 05B37554150316FE005E3D62 /* Build configuration list for PBXNativeTarget "makeheaders" */; buildPhases = ( 05B37549150316FD005E3D62 /* Sources */, 05B3754A150316FD005E3D62 /* Frameworks */, 05B3754B150316FD005E3D62 /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = makeheaders; productName = makeheaders; productReference = 05B3754D150316FD005E3D62 /* makeheaders */; productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 055C589115029D4000B34430 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0430; ORGANIZATIONNAME = "Plausible Labs Cooperative, Inc."; }; buildConfigurationList = 055C589415029D4000B34430 /* Build configuration list for PBXProject "AuthLDAP" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 055C588F15029D4000B34430; productRefGroup = 055C589B15029D4000B34430 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 055C589915029D4000B34430 /* tests */, 055C58B415029D9F00B34430 /* authldap */, 05B375351502FC2F005E3D62 /* lemon */, 05B3754C150316FD005E3D62 /* makeheaders */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ 055C589615029D4000B34430 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 05B375B615031DE5005E3D62 /* mockpf.c in Sources */, 05B375B715031DE5005E3D62 /* PXTestAssert.m in Sources */, 05B375B815031DE5005E3D62 /* PXTestCase.m in Sources */, 05B375B915031DE5005E3D62 /* PXTestCaseRunner.m in Sources */, 05B375BA15031DE5005E3D62 /* PXTestConsoleResultHandler.m in Sources */, 05B375BB15031DE5005E3D62 /* PXTestException.m in Sources */, 05B375BC15031DE5005E3D62 /* tests.m in Sources */, 05B375BD15031DE5005E3D62 /* TRArrayTests.m in Sources */, 05B375BE15031DE5005E3D62 /* TRAuthLDAPConfigTests.m in Sources */, 05B375BF15031DE5005E3D62 /* TRAutoreleasePoolTests.m in Sources */, 05B375C015031DE5005E3D62 /* TRConfigLexerTests.m in Sources */, 05B375C115031DE5005E3D62 /* TRConfigTests.m in Sources */, 05B375C215031DE5005E3D62 /* TRConfigTokenTests.m in Sources */, 05B375C315031DE5005E3D62 /* TRHashTests.m in Sources */, 05B375C415031DE5005E3D62 /* TRLDAPAccountRepositoryTests.m in Sources */, 05B375C515031DE5005E3D62 /* TRLDAPConnectionTests.m in Sources */, 05B375C615031DE5005E3D62 /* TRLDAPEntryTests.m in Sources */, 05B375C715031DE5005E3D62 /* TRLDAPGroupConfigTests.m in Sources */, 05B375C815031DE5005E3D62 /* TRLDAPSearchFilterTests.m in Sources */, 05B375C915031DE5005E3D62 /* TRLocalPacketFilterTests.m in Sources */, 05B375CA15031DE5005E3D62 /* TRObjectTests.m in Sources */, 05B375CB15031DE5005E3D62 /* TRPFAddressTests.m in Sources */, 05B375CC15031DE5005E3D62 /* TRStringTests.m in Sources */, 05B375CD15031DE5005E3D62 /* TRVPNSessionTests.m in Sources */, 05733B7A15DB7372009E53FA /* asprintf.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 055C58B115029D9F00B34430 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 05B375D815032B20005E3D62 /* TRConfigLexer.re in Sources */, 05B3758115031864005E3D62 /* TRConfigParser.lemon in Sources */, 05B374F41502FADC005E3D62 /* auth-ldap.m in Sources */, 05B374F51502FADC005E3D62 /* hash.c in Sources */, 05B374F81502FADC005E3D62 /* strlcpy.c in Sources */, 05B374FA1502FADC005E3D62 /* testplugin.c in Sources */, 05B374FD1502FADC005E3D62 /* TRArray.m in Sources */, 05B374FF1502FADC005E3D62 /* TRAuthLDAPConfig.m in Sources */, 05B375011502FADC005E3D62 /* TRAutoreleasePool.m in Sources */, 05B375031502FADC005E3D62 /* TRConfig.m in Sources */, 05B375061502FADC005E3D62 /* TRConfigToken.m in Sources */, 05B375081502FADC005E3D62 /* TREnumerator.m in Sources */, 05B3750A1502FADC005E3D62 /* TRHash.m in Sources */, 05B3750C1502FADC005E3D62 /* TRLDAPAccountRepository.m in Sources */, 05B3750E1502FADC005E3D62 /* TRLDAPConnection.m in Sources */, 05B375101502FADC005E3D62 /* TRLDAPEntry.m in Sources */, 05B375121502FADC005E3D62 /* TRLDAPGroupConfig.m in Sources */, 05B375141502FADC005E3D62 /* TRLDAPSearchFilter.m in Sources */, 05B375161502FADC005E3D62 /* TRLocalPacketFilter.m in Sources */, 05B375181502FADC005E3D62 /* TRLog.m in Sources */, 05B3751A1502FADC005E3D62 /* TRObject.m in Sources */, 05B3751C1502FADC005E3D62 /* TRPacketFilter.m in Sources */, 05B3751E1502FADC005E3D62 /* TRPFAddress.m in Sources */, 05B375201502FADC005E3D62 /* TRString.m in Sources */, 05B375231502FADC005E3D62 /* TRVPNSession.m in Sources */, 05B375241502FADC005E3D62 /* xmalloc.c in Sources */, 05733B7B15DB7372009E53FA /* asprintf.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 05B375321502FC2F005E3D62 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 05B375481502FC88005E3D62 /* lemon.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 05B37549150316FD005E3D62 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 05B3755715031709005E3D62 /* makeheaders.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 05B3755915031716005E3D62 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 05B375351502FC2F005E3D62 /* lemon */; targetProxy = 05B3755815031716005E3D62 /* PBXContainerItemProxy */; }; 05B3755B15031717005E3D62 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 05B3754C150316FD005E3D62 /* makeheaders */; targetProxy = 05B3755A15031717005E3D62 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ 055C58A715029D4000B34430 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CONFIG_H_MACROS = "TEST_DATA=\"\\\"${SRCROOT}/tests/data\\\"\" APPLE_RUNTIME=1 HAVE_FRAMEWORK_FOUNDATION=1 HAVE_INTTYPES_H=1 HAVE_MEMORY_H=1 HAVE_OBJC_OBJC_H=1 HAVE_PTHREAD=1 HAVE_STDINT_H=1 HAVE_STDLIB_H=1 HAVE_STRINGS_H=1 HAVE_STRING_H=1 HAVE_SYS_STAT_H=1 HAVE_SYS_TYPES_H=1 HAVE_UNISTD_H=1 PACKAGE_BUGREPORT=\"landonf@opendarwin.org\" PACKAGE_NAME=\"auth-ldap\" PACKAGE_STRING=\"auth-ldap\" PACKAGE_TARNAME=\"auth-ldap\" PACKAGE_URL=\"\" PACKAGE_VERSION=\"2.0\" STDC_HEADERS=1 _GNU_SOURCE=1"; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(CONFIG_H_MACROS)", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", "${SHARED_DERIVED_FILE_DIR}/${CURRENT_ARCH}", ); MACOSX_DEPLOYMENT_TARGET = 10.7; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; name = Debug; }; 055C58A815029D4000B34430 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CONFIG_H_MACROS = "TEST_DATA=\"\\\"${SRCROOT}/tests/data\\\"\" APPLE_RUNTIME=1 HAVE_FRAMEWORK_FOUNDATION=1 HAVE_INTTYPES_H=1 HAVE_MEMORY_H=1 HAVE_OBJC_OBJC_H=1 HAVE_PTHREAD=1 HAVE_STDINT_H=1 HAVE_STDLIB_H=1 HAVE_STRINGS_H=1 HAVE_STRING_H=1 HAVE_SYS_STAT_H=1 HAVE_SYS_TYPES_H=1 HAVE_UNISTD_H=1 PACKAGE_BUGREPORT=\"landonf@opendarwin.org\" PACKAGE_NAME=\"auth-ldap\" PACKAGE_STRING=\"auth-ldap\" PACKAGE_TARNAME=\"auth-ldap\" PACKAGE_URL=\"\" PACKAGE_VERSION=\"2.0\" STDC_HEADERS=1 _GNU_SOURCE=1"; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_PREPROCESSOR_DEFINITIONS = "$(CONFIG_H_MACROS)"; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", "${SHARED_DERIVED_FILE_DIR}/${CURRENT_ARCH}", ); MACOSX_DEPLOYMENT_TARGET = 10.7; SDKROOT = macosx; }; name = Release; }; 055C58AA15029D4000B34430 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PRECOMPILE_PREFIX_HEADER = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 055C58AB15029D4000B34430 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PRECOMPILE_PREFIX_HEADER = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 055C58B715029DA000B34430 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { EXECUTABLE_PREFIX = lib; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = ""; }; name = Debug; }; 055C58B815029DA000B34430 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { EXECUTABLE_PREFIX = lib; PRODUCT_NAME = "$(TARGET_NAME)"; USER_HEADER_SEARCH_PATHS = ""; }; name = Release; }; 05B3753E1502FC2F005E3D62 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { GCC_WARN_64_TO_32_BIT_CONVERSION = NO; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 05B3753F1502FC2F005E3D62 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { GCC_WARN_64_TO_32_BIT_CONVERSION = NO; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 05B37555150316FE005E3D62 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { GCC_WARN_64_TO_32_BIT_CONVERSION = NO; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 05B37556150316FE005E3D62 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { GCC_WARN_64_TO_32_BIT_CONVERSION = NO; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 055C589415029D4000B34430 /* Build configuration list for PBXProject "AuthLDAP" */ = { isa = XCConfigurationList; buildConfigurations = ( 055C58A715029D4000B34430 /* Debug */, 055C58A815029D4000B34430 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 055C58A915029D4000B34430 /* Build configuration list for PBXNativeTarget "tests" */ = { isa = XCConfigurationList; buildConfigurations = ( 055C58AA15029D4000B34430 /* Debug */, 055C58AB15029D4000B34430 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 055C58B615029DA000B34430 /* Build configuration list for PBXNativeTarget "authldap" */ = { isa = XCConfigurationList; buildConfigurations = ( 055C58B715029DA000B34430 /* Debug */, 055C58B815029DA000B34430 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 05B3753D1502FC2F005E3D62 /* Build configuration list for PBXNativeTarget "lemon" */ = { isa = XCConfigurationList; buildConfigurations = ( 05B3753E1502FC2F005E3D62 /* Debug */, 05B3753F1502FC2F005E3D62 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 05B37554150316FE005E3D62 /* Build configuration list for PBXNativeTarget "makeheaders" */ = { isa = XCConfigurationList; buildConfigurations = ( 05B37555150316FE005E3D62 /* Debug */, 05B37556150316FE005E3D62 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 055C589115029D4000B34430 /* Project object */; } openvpn-auth-ldap-auth-ldap-2.0.4/AuthLDAP.xcodeproj/project.xcworkspace/000077500000000000000000000000001332642612100262705ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/AuthLDAP.xcodeproj/project.xcworkspace/contents.xcworkspacedata000066400000000000000000000002311332642612100332260ustar00rootroot00000000000000 openvpn-auth-ldap-auth-ldap-2.0.4/LICENSE000066400000000000000000000222321332642612100177420ustar00rootroot00000000000000**************** * INTRODUCTION * **************** The vast majority of this implementation is subject to the standard 3-clause BSD license. Copyright is held by Three Rings Design and Landon Fuller, and the license and official copyright can be found at the bottom of this file. Small portions of the implementation were taken from various sources, including: - FreeBSD libc (strlcpy) - FreeBSD kernel (pf ioctl validation) - kazlib (hash table implementation) - PLInstrument (test runner framework) - SenTestCase (test assertion macros) Associated copyrights and licenses are documented below. All code included in the final product are either made available under the BSD license, or under an compatible and equivalently permissive license. Some additional sources are included with this distribution and used as a part of the build process; they are not linked with the final product: - The lemon parser generator - Public Domain (http://www.hwaci.com/sw/lemon/) - Makeheaders - GPL (http://www.hwaci.com/sw/mkhdr/) *************************** * COPYRIGHTS AND LICENSES * *************************** The src/strlcpy.c and src/strlcpy.h files were taken from FreeBSD libc and are subject to the following copyright: Copyright (c) 1998 Todd C. Miller All rights reserved. Please refer to the strlcpy source files for a copy of their (BSD) license. The src/hash.c and src/hash.h files were taken from kazlib, and are subject to the following copyright and license: Copyright (C) 1997 Kaz Kylheku Free Software License: All rights are reserved by the author, with the following exceptions: Permission is granted to freely reproduce and distribute this software, possibly in exchange for a fee, provided that this copyright notice appears intact. Permission is also granted to adapt this software to produce derivative works, as long as the modified versions carry this copyright notice and additional notices stating that the work has been modified. This source code may be translated into executable form and incorporated into proprietary software; there is no requirement for such software to contain a copyright notice related to this source. Small portions of test/mockpf.c and test/mockpf.h were taken from the pf(4) kernel implementation. These files are used only for the unit tests, and thus not included in the final output. They are subject to the following copyright and license: Copyright (c) 2002 Cedric Berger All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The Objective-C test framework was derived from Plausible Labs' PLInstrument. These files are used only for the unit tests, and thus not included in the final output. They are subject to the following copyright and license: Copyright (c) 2012 Landon Fuller Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The test/PXTestAssert.h, test/PXTestAssert.m, PXTestException.h, and PXTestException.m files provide the assertion macros used in the unit test system. These files were derived from Google's GTM project, which in turn is derived from Sen:Te's OCUnit. These files are used only for the unit tests, and thus not included in the final output. They are subject to the following copyright and license: Copyright 2007-2008 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Portions of this file fall under the following license, marked with SENTE_BEGIN - SENTE_END Copyright (c) 1997-2005, Sen:te (Sente SA). All rights reserved. Use of this source code is governed by the following license: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Sente SA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Note: this license is equivalent to the FreeBSD license. All other code is subject to the following copyright and license: Copyright (c) 2006 - 2007 Three Rings Design, Inc. Copyright (c) 2005 - 2012 Landon Fuller All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holders nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. openvpn-auth-ldap-auth-ldap-2.0.4/Makefile.in000066400000000000000000000004461332642612100210050ustar00rootroot00000000000000top_srcdir= @top_srcdir@ SUBDIR= tools \ src \ tests \ docs include Mk/subdir.mk include Mk/autoconf.mk all:: clean:: distclean:: rm -f config.log config.status configure.lineno config.cache config.h rm -rf autom4te.cache rm -f Makefile Mk/autoconf.mk Mk/compile.mk Mk/subdir.mk openvpn-auth-ldap-auth-ldap-2.0.4/Mk/000077500000000000000000000000001332642612100173035ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/Mk/autoconf.mk.in000066400000000000000000000024151332642612100220610ustar00rootroot00000000000000SHELL = @SHELL@ CC = @CC@ CFLAGS = @CFLAGS@ @DEFS@ -Wall OBJCFLAGS = -fPIC @OBJCFLAGS@ ${OBJC_RUNTIME_FLAGS} ${OBJC_PTHREAD_CFLAGS} -fno-strict-aliasing ${CFLAGS} OBJC_LIBS = -fPIC @OBJC_LIBS@ ${OBJC_PTHREAD_LIBS} OBJC_RUNTIME = @OBJC_RUNTIME@ OBJC_RUNTIME_FLAGS = @OBJC_RUNTIME_FLAGS@ OBJC_PTHREAD_LIBS = @OBJC_PTHREAD_LIBS@ OBJC_PTHREAD_CFLAGS = @OBJC_PTHREAD_CFLAGS@ PLUGIN_LD = @PLUGIN_LD@ PLUGIN_LD_FLAGS = @PLUGIN_LD_FLAGS@ PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ PLUGIN_SUFFIX = @PLUGIN_SUFFIX@ PLUGIN_FILE = @PLUGIN_FILE@ MAKE_PLUGIN = @MAKE_PLUGIN@ INSTALL_PLUGIN = @INSTALL_PLUGIN@ CLEAN_PLUGIN = @CLEAN_PLUGIN@ LDAP_LIBS = @LDAP_LIBS@ LDAP_CFLAGS = @LDAP_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ OPENVPN_CFLAGS = @OPENVPN_CFLAGS@ LDFLAGS = @LDFLAGS@ AR = @AR@ RANLIB = @RANLIB@ INSTALL = @INSTALL@ LN_S = @LN_S@ RE2C = @RE2C@ DOXYGEN = @DOXYGEN@ prefix = @prefix@ sysconfdir = @sysconfdir@ exec_prefix = @exec_prefix@ bindir = @bindir@ datarootdir = @datarootdir@ datadir = @datadir@ libdir = @libdir@ localstatedir = @localstatedir@ infodir = @infodir@ SILENT = @ openvpn-auth-ldap-auth-ldap-2.0.4/Mk/compile.mk.in000066400000000000000000000011021332642612100216630ustar00rootroot00000000000000.SUFFIXES: .m .lemon .re # Disable GNU make's removal intermediate files, we handle this manually .SECONDARY: .m.o: ${CC} ${OBJCFLAGS} -c $< -o $@ -I${srcdir} -I${top_srcdir}/src -I${top_builddir} -I${top_builddir}/src -I. -I${top_srcdir}/tests -I${top_builddir}/tests .c.o: ${CC} ${CFLAGS} -c $< -o $@ -I${srcdir} -I${top_srcdir}/src -I${top_builddir} -I${top_builddir}/src -I. -I${top_srcdir}/tests -I${top_builddir}/tests .lemon.m: ${top_builddir}/tools/lemon -T${top_srcdir}/tools/lempar.c -m -q $< -O$@ ${top_builddir}/tools/makeheaders $@ .re.m: ${RE2C} -o $@ $< openvpn-auth-ldap-auth-ldap-2.0.4/Mk/subdir.mk.in000066400000000000000000000025741332642612100215410ustar00rootroot00000000000000.PHONY : all pre-all .PHONY : clean distclean .PHONY : install .PHONY : test .PHONY : docs all:: pre-all @if test x"$(SUBDIR)" != "x"; then \ for subdir in $(SUBDIR); do\ echo ===\> making $@ in ${DIRPRFX}$$subdir; \ ( cd $$subdir && $(MAKE) DIRPRFX=${DIRPRFX}$$subdir/ $@) || exit 1; \ done \ fi pre-all:: clean:: @if test x"$(SUBDIR)" != "x"; then \ for subdir in $(SUBDIR); do\ echo ===\> making $@ in ${DIRPRFX}$$subdir; \ ( cd $$subdir && $(MAKE) DIRPRFX=${DIRPRFX}$$subdir/ $@) || exit 1; \ done \ fi distclean:: clean @if test x"$(SUBDIR)" != "x"; then \ for subdir in $(SUBDIR); do\ echo ===\> making $@ in ${DIRPRFX}$$subdir; \ ( cd $$subdir && $(MAKE) DIRPRFX=${DIRPRFX}$$subdir/ $@) || exit 1; \ done \ fi install:: @if test x"$(SUBDIR)" != "x"; then \ for subdir in $(SUBDIR); do\ echo ===\> making $@ in ${DIRPRFX}$$subdir; \ ( cd $$subdir && $(MAKE) DIRPRFX=${DIRPRFX}$$subdir/ $@) || exit 1; \ done \ fi test:: all @if test x"$(SUBDIR)" != "x"; then \ for subdir in $(SUBDIR); do\ echo ===\> making $@ in ${DIRPRFX}$$subdir; \ ( cd $$subdir && $(MAKE) DIRPRFX=${DIRPRFX}$$subdir/ $@) || exit 1; \ done \ fi docs:: all @if test x"$(SUBDIR)" != "x"; then \ for subdir in $(SUBDIR); do\ echo ===\> making $@ in ${DIRPRFX}$$subdir; \ ( cd $$subdir && $(MAKE) DIRPRFX=${DIRPRFX}$$subdir/ $@) || exit 1; \ done \ fi openvpn-auth-ldap-auth-ldap-2.0.4/README.md000066400000000000000000000071241332642612100202170ustar00rootroot00000000000000## Description The OpenVPN Auth-LDAP Plugin implements username/password authentication via LDAP for OpenVPN 2.x. ### Features * User authentication against LDAP. * Simple Apache-style configuration file. * LDAP group-based access restrictions. * Integration with the OpenBSD packet filter, supporting adding and removing VPN clients from PF tables based on group membership. * Tested against OpenLDAP, the plugin will authenticate against any LDAP server that supports LDAP simple binds -- including Active Directory. * Supports OpenVPN Challenge/Response protocol, enabling it to be used in combination with one time password systems like Google Authenticator ## Building ### Requirements * OpenLDAP Headers and Library * GNU Objective-C Compiler * OpenVPN Plugin Header (included with the OpenVPN sources) * [re2c](http://www.re2c.org/) (used for the configuration file lexer) To build, you will need to configure the sources appropriately. Example: ``` ./configure --prefix=/usr/local --with-openldap=/usr/local --with-openvpn=/home/sean/work/openvpn-2.0.2 ``` The module will be built in src/openvpn-auth-ldap.so and installed as `${prefix}/lib/openvpn-auth-ldap.so`. #### Building On Ubuntu 16.04 #### The following steps were tested on a clean Ubuntu 16.04 LTS Amazon EC2 m5.large instance in January 2018 (source AMI: ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-20180109 - ami-41e0b93b). If you wish to repeat this process, follow these steps on your own machine: ``` git clone https://github.com/snowrider311/openvpn-auth-ldap cd openvpn-auth-ldap/ ./ubuntu_16.04_lts_build.sh ``` The `ubuntu_16.04_lts_build.sh` script will install all needed build dependencies, perform the build, and install `openvpn-auth-ldap.so` to `/usr/local/lib`. If you then wish to create a Debian package, you can then run this script: ``` ./ubuntu_16.04_lts_package.sh ``` That script will install [FPM](https://github.com/jordansissel/fpm) and then use it to build a Debian package. If you then run `sudo dpkg -i openvpn-auth-ldap-snowrider311_2.0.3-1_amd64.deb`, then `openvpn-auth-ldap.so` will be installed to `/usr/lib/openvpn`, the same location as the standard, unforked `openvpn-auth-ldap` Debian package installs to. Note: Superuser privileges are required to run these scripts. ## Usage Add the following to your OpenVPN configuration file (adjusting the plugin path as required): ``` plugin /usr/local/lib/openvpn-auth-ldap.so "" ``` The config directive must point to an auth-ldap configuration file. An example configuration file is provided with the distribution, or see the [Configuration](../../wiki/Configuration) page. ## Security *Please report all security issues directly to landonf+security (at) bikemonkey (dot) org.* Through the use of extensive unit testing, valgrind, and regression testing, we are very confident in the overall code quality of the plugin. There has been one security vulnerability to date, due to misinterpretation of LDAP RFCs. * 2006-12-02: OpenVPN Auth-LDAP would accept empty passwords when validating against Novell Directory Server. This is known to not affect default installs of OpenLDAP (our test platform). Strict implementation of the LDAP RFCs requires that a directory server treat a bind with a valid DN and an empty password as an "anonymous" bind. If anonymous binds are enabled, this could lead to password bypass. ## Support Plausible Labs Cooperative is available to provide custom development or support for this plugin. If you require specific features or additions, please [contact us](http://www.plausible.coop/about/) for more information. openvpn-auth-ldap-auth-ldap-2.0.4/aclocal.m4000066400000000000000000000303241332642612100205760ustar00rootroot00000000000000builtin(include,pthread.m4) builtin(include,platform.m4) builtin(include,framework.m4) #------------------------------------------------------------------------ # OD_OBJC_RUNTIME -- # # Determine the default, working Objective C runtime # # Arguments: # None. # # Requires: # none # # Depends: # AC_PROG_OBJC from objc.m4 # # Results: # # Adds a --with-objc-runtime switch to configure. # Result is cached. # # Defines one of the following preprocessor macros: # APPLE_RUNTIME GNU_RUNTIME # # Substitutes the following variables: # OBJC_RUNTIME OBJC_RUNTIME_FLAGS OBJC_LIBS # OBJC_PTHREAD_CFLAGS OBJC_PTHREAD_LIBS #------------------------------------------------------------------------ AC_DEFUN([OD_OBJC_RUNTIME],[ AC_REQUIRE([AC_PROG_OBJC]) AC_ARG_WITH(objc-runtime, AC_HELP_STRING([--with-objc-runtime], [Specify either "GNU" or "apple"]), [with_objc_runtime=${withval}]) if test x"${with_objc_runtime}" != x; then case "${with_objc_runtime}" in GNU) ;; apple) ;; *) AC_MSG_ERROR([${with_objc_runtime} is not a valid argument to --with-objc-runtime. Please specify either "GNU" or "apple"]) ;; esac fi AC_LANG_PUSH([Objective C]) # Check for common header, objc/objc.h AC_CHECK_HEADERS([objc/objc.h], ,[AC_MSG_ERROR([Can't locate Objective C runtime headers])]) # Save LIBS & OBJCFLAGS # depending on whether the cache is used, # the variables may or may not be modified. OLD_LIBS="${LIBS}" OLD_OBJCFLAGS="${OBJCFLAGS}" # Add -lobjc and -fobjc-exceptions. The following tests will ensure that the library exists and # functions with the detected Objective C compiler OBJCFLAGS="${OBJCFLAGS} -fobjc-exceptions" LIBS="${LIBS} -lobjc -fobjc-exceptions" # Test if pthreads are required to link against # libobjc - this is the case on FreeBSD. AC_MSG_CHECKING([if linking libobjc requires pthreads]) AC_CACHE_VAL(od_cv_objc_req_pthread, [ # First, test if objc links without pthreads # The following uses quadrigraphs # '@<:@' = '[' # '@:>@' = ']' AC_LINK_IFELSE([ AC_LANG_PROGRAM([ #include #include ], [ Object *obj = @<:@Object alloc@:>@; puts(@<:@obj name@:>@); ]) ], [ # Linked without -pthread od_cv_objc_req_pthread="no" ], [ # Failed to link without -pthread od_cv_objc_req_pthread="yes" ] ) # If the above failed, try with pthreads if test x"${od_cv_objc_req_pthread}" = x"yes"; then LIBS="${LIBS} ${PTHREAD_LIBS}" OBJCFLAGS="${OBJCFLAGS} ${PTHREAD_CFLAGS}" AC_LINK_IFELSE([ AC_LANG_PROGRAM([ #include #include ], [ Object *obj = @<:@Object alloc@:>@; puts(@<:@obj name@:>@); ]) ], [ # Linked with -lpthread od_cv_objc_req_pthread="yes" ], [ # Failed to link against objc at all # This will be caught in the runtime # checks below od_cv_objc_req_pthread="no" ] ) fi ]) AC_MSG_RESULT(${od_cv_objc_req_pthread}) if test x"${od_cv_objc_req_pthread}" = x"no"; then OBJC_LIBS="${OBJC_LIBS} -lobjc" OBJC_PTHREAD_LIBS="${PTHREAD_LIBS} -fobjc-exceptions" OBJC_PTHREAD_CFLAGS="${PTHREAD_CFLAGS} -fobjc-exceptions" elif test x"${od_cv_objc_req_pthread}" = x"yes"; then OBJC_LIBS="${OBJC_LIBS} -lobjc ${PTHREAD_LIBS} -fobjc-exceptions" OBJCFLAGS="${OBJCFLAGS} ${PTHREAD_CFLAGS} -fobjc-exceptions" fi if test x"${with_objc_runtime}" = x || test x"${with_objc_runtime}" = x"apple"; then AC_MSG_CHECKING([for Apple Objective-C runtime]) AC_CACHE_VAL(od_cv_objc_runtime_apple, [ # The following uses quadrigraphs # '@<:@' = '[' # '@:>@' = ']' AC_LINK_IFELSE([ AC_LANG_PROGRAM([ #include #include ], [ id class = objc_lookUpClass("Object"); id obj = @<:@class alloc@:>@; puts(@<:@obj name@:>@); ]) ], [ od_cv_objc_runtime_apple="yes" ], [ od_cv_objc_runtime_apple="no" ] ) ]) AC_MSG_RESULT(${od_cv_objc_runtime_apple}) else od_cv_objc_runtime_apple="no" fi if test x"${with_objc_runtime}" = x || test x"${with_objc_runtime}" = x"GNU"; then AC_MSG_CHECKING([for GNU Objective C runtime]) AC_CACHE_VAL(od_cv_objc_runtime_gnu, [ # The following uses quadrigraphs # '@<:@' = '[' # '@:>@' = ']' AC_LINK_IFELSE([ AC_LANG_PROGRAM([ #include #ifdef __GNU_LIBOBJC__ #include #else #include #endif ], [ #ifdef __GNU_LIBOBJC_ Class class = objc_lookUpClass("Object"); puts(class_getName(class));_ #else id class = objc_lookup_class("Object"); id obj = @<:@class alloc@:>@; puts(@<:@obj name@:>@); #endif ]) ], [ od_cv_objc_runtime_gnu="yes" ], [ od_cv_objc_runtime_gnu="no" ] ) ]) AC_MSG_RESULT(${od_cv_objc_runtime_gnu}) else od_cv_objc_runtime_gnu="no" fi # Apple runtime is prefered if test x"${od_cv_objc_runtime_apple}" = x"yes"; then OBJC_RUNTIME="APPLE_RUNTIME" AC_MSG_NOTICE([Using Apple Objective-C runtime]) AC_DEFINE([APPLE_RUNTIME], 1, [Define if using the Apple Objective-C runtime and compiler.]) elif test x"${od_cv_objc_runtime_gnu}" = x"yes"; then OBJC_RUNTIME="GNU_RUNTIME" AC_MSG_NOTICE([Using GNU Objective-C runtime]) AC_DEFINE([GNU_RUNTIME], 1, [Define if using the GNU Objective-C runtime and compiler.]) else AC_MSG_FAILURE([Could not locate a working Objective-C runtime.]) fi # Restore LIBS & OBJCFLAGS LIBS="${OLD_LIBS}" OBJCFLAGS="${OLD_OBJCFLAGS}" AC_SUBST([OBJC_RUNTIME]) AC_SUBST([OBJC_RUNTIME_FLAGS]) AC_SUBST([OBJC_LIBS]) AC_SUBST([OBJC_PTHREAD_LIBS]) AC_SUBST([OBJC_PTHREAD_CFLAGS]) AC_LANG_POP([Objective C]) ]) #------------------------------------------------------------------------ # OD_OPENLDAP -- # # Locate the OpenLDAP libraries and headers # # Arguments: # None. # # Requires: # none # # Depends: # none # # Results: # # Adds a --with-openldap switch to configure. # Result is cached. # # Substitutes the following variables: # LDAP_LIBS LDAP_CFLAGS #------------------------------------------------------------------------ AC_DEFUN([OD_OPENLDAP],[ AC_REQUIRE([AC_PROG_CC]) AC_ARG_WITH(openldap, AC_HELP_STRING([--with-openldap], [Specify the openldap installation location]), [with_openldap=${withval}]) # Save LIBS, CFLAGS # depending on whether the cache is used, # the variables may or may not be modified. OLD_LIBS="${LIBS}" OLD_CFLAGS="${CFLAGS}" LDAP_LIBS="-lldap -llber" LDAP_CFLAGS="" if test x"${with_openldap}" != x; then LDAP_LIBS="${LDAP_LIBS} -L${with_openldap}/lib" LDAP_CFLAGS="${LDAP_CFLAGS} -I${with_openldap}/include" fi # Add -lldap. The following tests will ensure that the library exists and functions with the detected C compiler LIBS="${LIBS} ${LDAP_LIBS}" CFLAGS="${CFLAGS} ${LDAP_CFLAGS}" AC_MSG_CHECKING([for openldap]) AC_CACHE_VAL(od_cv_openldap, [ AC_LINK_IFELSE([ AC_LANG_PROGRAM([ #include ], [ int flag = LDAP_OPT_X_TLS_NEVER; void *fptr = ldap_result; ]) ], [ # Failed od_cv_openldap="yes" ], [ # Success od_cv_openldap="no" ] ) ]) AC_MSG_RESULT(${od_cv_openldap}) if test x"${od_cv_openldap}" = x"no"; then AC_MSG_FAILURE([Could not locate a working OpenLDAP library installation. Try --with-openldap=]) fi # Restore LIBS & CFLAGS LIBS="${OLD_LIBS}" CFLAGS="${OLD_CFLAGS}" AC_SUBST([LDAP_CFLAGS]) AC_SUBST([LDAP_LIBS]) ]) #------------------------------------------------------------------------ # OD_OPENVPN_HEADER -- # # Locate the OpenVPN plugin header # # Arguments: # None. # # Requires: # none # # Depends: # none # # Results: # # Adds a --with-openvpn switch to configure. # Result is cached. # # Substitutes the following variables: # OPENVPN_CFLAGS #------------------------------------------------------------------------ AC_DEFUN([OD_OPENVPN_HEADER],[ AC_REQUIRE([AC_PROG_CC]) AC_ARG_WITH(openvpn, AC_HELP_STRING([--with-openvpn], [Specify the path to the OpenVPN source]), [with_openvpn=${withval}]) if test x"${with_openvpn}" = "x"; then AC_MSG_ERROR([You must specify the location of the OpenVPN source code with --with-openvpn]) else OPENVPN_CFLAGS="-I${with_openvpn}" fi # Save CFLAGS OLD_CFLAGS="${CFLAGS}" CFLAGS="${CFLAGS} ${OPENVPN_CFLAGS}" AC_MSG_CHECKING([for openvpn-plugin.h]) AC_CACHE_VAL(od_cv_openvpn, [ AC_LINK_IFELSE([ AC_LANG_PROGRAM([ #include ], [ int flag = OPENVPN_PLUGIN_UP; ]) ], [ # Failed od_cv_openvpn="yes" ], [ # Success od_cv_openvpn="no" ] ) ]) AC_MSG_RESULT(${od_cv_openvpn}) if test x"${od_cv_openvpn}" = x"no"; then AC_MSG_FAILURE([Could not locate a working openvpn source tree.]) fi # Restore LIBS & CFLAGS LIBS="${OLD_LIBS}" CFLAGS="${OLD_CFLAGS}" AC_SUBST([OPENVPN_CFLAGS]) ]) #------------------------------------------------------------------------ # TR_PF_IOCTL -- # # Locate the pf(4) headers # # Arguments: # None. # # Requires: # none # # Depends: # none # # Results: # # Defines the following preprocessor macros: # OPENVPN_CFLAGS #------------------------------------------------------------------------ AC_DEFUN([TR_PF_IOCTL],[ AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([for BSD pf(4) support]) AC_CACHE_VAL(tr_cv_pf_ioctl, [ AC_LINK_IFELSE([ AC_LANG_PROGRAM([ #include #include #include #include #include ], [ unsigned long req = DIOCRCLRTABLES; ]) ], [ # Failed tr_cv_pf_ioctl="yes" ], [ # Success tr_cv_pf_ioctl="no" ] ) ]) AC_MSG_RESULT(${tr_cv_pf_ioctl}) if test x"${tr_cv_pf_ioctl}" = x"no"; then AC_MSG_WARN([pf(4) table support will not be included.]) else AC_DEFINE([HAVE_PF], [1], [Define to enable pf(4) table support.]) AC_DEFINE([PF_DEV_PATH], ["/dev/pf"], [Path to the pf(4) device.]) fi ]) #------------------------------------------------------------------------ # TR_OPENSSL -- # # Locate the OpenSSL libraries and headers # # Arguments: # None. # # Requires: # none # # Depends: # none # # Results: # # Adds a --with-openssl switch to configure. # Result is cached. # # Substitutes the following variables: # OPENSSL_LIBS OPENSSL_CFLAGS #------------------------------------------------------------------------ AC_DEFUN([TR_OPENSSL],[ AC_REQUIRE([AC_PROG_CC]) AC_ARG_WITH(openssl, AC_HELP_STRING([--with-openssl], [Specify the openssl installation location]), [with_openssl=${withval}]) # Save LIBS, CFLAGS # depending on whether the cache is used, # the variables may or may not be modified. OLD_LIBS="${LIBS}" OLD_CFLAGS="${CFLAGS}" OPENSSL_LIBS="-lssl -lcrypto" OPENSSL_CFLAGS="" if test x"${with_openssl}" != x; then OPENSSL_LIBS="${OPENSSL_LIBS} -L${with_openssl}/lib" OPENSSL_CFLAGS="${OPENSSL_CFLAGS} -I${with_openssl}/include" fi # Add -lssl. The following tests will ensure that the library exists and functions with the detected C compiler LIBS="${LIBS} ${OPENSSL_LIBS}" CFLAGS="${CFLAGS} ${OPENSSL_CFLAGS}" AC_MSG_CHECKING([for openssl]) AC_CACHE_VAL(od_cv_openssl, [ AC_LINK_IFELSE([ AC_LANG_PROGRAM([ #include ], [ CRYPTO_set_id_callback(NULL); ]) ], [ # Failed od_cv_openssl="yes" ], [ # Success od_cv_openssl="no" ] ) ]) AC_MSG_RESULT(${od_cv_openssl}) if test x"${od_cv_openssl}" = x"no"; then AC_MSG_FAILURE([Could not locate a working OpenSSL library installation. Try --with-openssl=]) fi # Restore LIBS & CFLAGS LIBS="${OLD_LIBS}" CFLAGS="${OLD_CFLAGS}" AC_SUBST([OPENSSL_CFLAGS]) AC_SUBST([OPENSSL_LIBS]) ]) #------------------------------------------------------------------------ # TR_WERROR -- # # Enable -Werror # # Arguments: # None. # # Requires: # none # # Depends: # none # # Results: # Modifies CFLAGS variable. #------------------------------------------------------------------------ AC_DEFUN([TR_WERROR],[ AC_REQUIRE([AC_PROG_CC]) AC_ARG_ENABLE(werror, AC_HELP_STRING([--enable-werror], [Add -Werror to CFLAGS. Used for development.]), [enable_werror=${enableval}], [enable_werror=no]) if test x"$enable_werror" != "xno"; then CFLAGS="$CFLAGS -Werror" fi ]) openvpn-auth-ldap-auth-ldap-2.0.4/auth-ldap.conf000066400000000000000000000032641332642612100214670ustar00rootroot00000000000000 # LDAP server URL URL ldap://ldap1.example.org # Bind DN (If your LDAP server doesn't support anonymous binds) # BindDN uid=Manager,ou=People,dc=example,dc=com # Bind Password # Password SecretPassword # Network timeout (in seconds) Timeout 15 # Enable Start TLS TLSEnable yes # Follow LDAP Referrals (anonymously) FollowReferrals yes # TLS CA Certificate File TLSCACertFile /usr/local/etc/ssl/ca.pem # TLS CA Certificate Directory TLSCACertDir /etc/ssl/certs # Client Certificate and key # If TLS client authentication is required TLSCertFile /usr/local/etc/ssl/client-cert.pem TLSKeyFile /usr/local/etc/ssl/client-key.pem # Cipher Suite # The defaults are usually fine here # TLSCipherSuite ALL:!ADH:@STRENGTH # Base DN BaseDN "ou=People,dc=example,dc=com" # User Search Filter SearchFilter "(&(uid=%u)(accountStatus=active))" # Require Group Membership RequireGroup false # Add non-group members to a PF table (disabled) #PFTable ips_vpn_users # Uncomment and set to true to support OpenVPN Challenge/Response #PasswordIsCR false # Default is true. Match full user DN if true, uid only if false. # RFC2307bis true # Default is true. Uncomment and set to false if you want to use a Search operation to determine group # membership instead of Compare. Lower performance, so Compare should generally be used, but Search is # required in certain LDAP environments. # UseCompareOperation true BaseDN "ou=Groups,dc=example,dc=com" SearchFilter "(|(cn=developers)(cn=artists))" MemberAttribute uniqueMember # Add group members to a PF table (disabled) #PFTable ips_vpn_eng openvpn-auth-ldap-auth-ldap-2.0.4/config.guess000077500000000000000000001154431332642612100212640ustar00rootroot00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-07-23' # This file 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # This shell variable is my proudest work .. or something. --bje set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ; (old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old) || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ; dummy=$tmpdir/dummy ; files="$dummy.c $dummy.o $dummy.rel $dummy" ; trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; rm -f $files ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; unset files' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. eval $set_cc_for_build cat <$dummy.s .data \$Lformat: .byte 37,100,45,37,120,10,0 # "%d-%x\n" .text .globl main .align 4 .ent main main: .frame \$30,16,\$26,0 ldgp \$29,0(\$27) .prologue 1 .long 0x47e03d80 # implver \$0 lda \$2,-1 .long 0x47e20c21 # amask \$2,\$1 lda \$16,\$Lformat mov \$0,\$17 not \$1,\$18 jsr \$26,printf ldgp \$29,0(\$26) mov 0,\$16 jsr \$26,exit .end main EOF $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null if test "$?" = 0 ; then case `$dummy` in 0-0) UNAME_MACHINE="alpha" ;; 1-0) UNAME_MACHINE="alphaev5" ;; 1-1) UNAME_MACHINE="alphaev56" ;; 1-101) UNAME_MACHINE="alphapca56" ;; 2-303) UNAME_MACHINE="alphaev6" ;; 2-307) UNAME_MACHINE="alphaev67" ;; 2-1307) UNAME_MACHINE="alphaev68" ;; 3-1307) UNAME_MACHINE="alphaev7" ;; esac fi rm -f $dummy.s $dummy && rmdir $tmpdir echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; DRS?6000:UNIX_SV:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7 && exit 0 ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD $dummy.c -o $dummy \ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Night_Hawk:*:*:PowerMAX_OS) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`$dummy` if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi rm -f $dummy.c $dummy && rmdir $tmpdir fi ;; esac echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3D:*:*:*) echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) # Determine whether the default compiler uses glibc. eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #if __GLIBC__ >= 2 LIBC=gnu #else LIBC= #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` rm -f $dummy.c && rmdir $tmpdir echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:3*) echo i386-pc-interix3 exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i386-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` rm -f $dummy.c && rmdir $tmpdir test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` rm -f $dummy.c && rmdir $tmpdir test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) echo `uname -p`-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 rm -f $dummy.c $dummy && rmdir $tmpdir # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: openvpn-auth-ldap-auth-ldap-2.0.4/config.sub000077500000000000000000000714531332642612100207310ustar00rootroot00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-07-03' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file 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., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k \ | m32r | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ | mipsisa64 | mipsisa64el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c54x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipstx39 | mipstx39el \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon) basic_machine=i686-pc ;; pentiumii | pentium2) basic_machine=i686-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3d) basic_machine=alpha-cray os=-unicos ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; windows32) basic_machine=i386-pc os=-windows32-msvcrt ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; c4x*) basic_machine=c4x-none os=-coff ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto*) os=-nto-qnx ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -ptx*) vendor=sequent ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: openvpn-auth-ldap-auth-ldap-2.0.4/configure.ac000066400000000000000000000030171332642612100212230ustar00rootroot00000000000000AC_PREREQ(2.57) AC_INIT(auth-ldap, [2.0], landonf@opendarwin.org) AC_CONFIG_SRCDIR(${srcdir}/src/auth-ldap.m) AC_CONFIG_HEADERS(config.h) AC_CANONICAL_SYSTEM # Compiler AC_PROG_CC(clang gcc) AC_PROG_CC_C99 AC_PROG_OBJC(clang gcc) TR_WERROR AC_CACHE_SAVE # Programs AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AC_CHECK_TOOL(RANLIB, ranlib, :) AC_CHECK_TOOL(AR, ar, :) AC_PATH_PROG([RE2C], [re2c], [no]) if test x"$RE2C" = x"no"; then AC_MSG_ERROR([re2c was not found in your PATH. It can be downloaded from http://re2c.org]) fi AC_PATH_PROG([DOXYGEN], [doxygen], [no]) if test x"$DOXYGEN" = x"no"; then DOXYGEN="false" fi AC_PATH_PROG([DOT], [dot], [no]) if test x"$DOT" = x"no"; then DOTDIR="" else DOTDIR=`AS_DIRNAME([$DOT])` fi AC_SUBST([DOTDIR]) AC_CACHE_SAVE # Headers AC_HEADER_STDC AC_CACHE_SAVE # Threads ACX_PTHREAD AC_CACHE_SAVE # Platform OD_CONFIG_PLUGIN TR_PF_IOCTL AC_DEFINE([_GNU_SOURCE], 1, [Required for vasprintf() on glibc systems]) AC_CACHE_SAVE # Functions AC_CHECK_FUNCS([strlcpy]) AC_CACHE_SAVE # Libraries OD_OPENLDAP TR_OPENSSL AC_CHECK_FRAMEWORK(Foundation, NSStringFromSelector, [ AC_DEFINE(HAVE_FRAMEWORK_FOUNDATION, 1, [Define if you have the Foundation framework.]) OBJC_LIBS="${OBJC_LIBS} -framework Foundation" ]) AC_CACHE_SAVE # OpenVPN OD_OPENVPN_HEADER AC_CACHE_SAVE # Objective-C Runtime OD_OBJC_RUNTIME AC_CACHE_SAVE # Output AC_CONFIG_FILES([ Makefile docs/Makefile docs/doxyfile Mk/autoconf.mk Mk/compile.mk Mk/subdir.mk src/Makefile tests/Makefile tools/Makefile ]) AC_OUTPUT openvpn-auth-ldap-auth-ldap-2.0.4/docs/000077500000000000000000000000001332642612100176645ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/docs/Makefile.in000077500000000000000000000020331332642612100217320ustar00rootroot00000000000000srcdir= @srcdir@ top_srcdir= @top_srcdir@ top_builddir= @top_builddir@ VPATH= @srcdir@ include ${top_builddir}/Mk/autoconf.mk include ${top_builddir}/Mk/compile.mk include ${top_builddir}/Mk/subdir.mk SOURCEDIR= ${srcdir}/xml XHTMLDIR= xhtml STYLESHEET= http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl XSTYLESHEET= http://docbook.sourceforge.net/release/xsl/current/xhtml/chunk.xsl RESOURCES= ${srcdir}/resources/ CSS_STYLESHEET= docbook.css STRINGPARAMS= --stringparam html.stylesheet ${CSS_STYLESHEET} .PHONY: all .PHONY: clean #.PHONY: install .PHONY: xhtml .PHONY: check .PHONY: tidy codedocs:: ${DOXYGEN} doxyfile manual:: mkdir -p ${XHTMLDIR} install ${RESOURCES}${CSS_STYLESHEET} ${XHTMLDIR} xsltproc --xinclude ${STRINGPARAMS} -o "${XHTMLDIR}/" "${XSTYLESHEET}" "${SOURCEDIR}/auth-ldap.xml" docs:: codedocs manual check: xmllint --xinclude --noout "${SOURCEDIR}/auth-ldap.xml" clean:: rm -rf ${HTMLDIR} ${XHTMLDIR} code distclean:: clean rm -f Makefile doxyfile openvpn-auth-ldap-auth-ldap-2.0.4/docs/doxyfile.in000066400000000000000000001455521332642612100220530ustar00rootroot00000000000000# Doxyfile 1.5.2 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file that # follow. The default is UTF-8 which is also the encoding used for all text before # the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into # libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of # possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = "OpenVPN Auth-LDAP" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @PACKAGE_VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = code # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, # Italian, Japanese, Japanese-en (Japanese with English messages), Korean, # Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, # Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like the Qt-style comments (thus requiring an # explicit @brief command for a brief description. JAVADOC_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for Java. # For instance, namespaces will be presented as packages, qualified scopes # will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to # include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = YES # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = YES # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from the # version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = NO # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @top_srcdir@/src # This tag can be used to specify the character encoding of the source files that # doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default # input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. # See http://www.gnu.org/software/libiconv for the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = YES # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the output. # The symbol name can be a fully qualified name, a word, or if the wildcard * is used, # a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentstion. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compressed HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = YES # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = YES # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = HAVE_PF=yes # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to # produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to # specify the directory where the mscgen tool resides. If left empty the tool is assumed to # be found in the default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a call dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected # functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will # generate a caller dependency graph for every global function or class method. # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable caller graphs for selected # functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = @DOTDIR@ # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen will always # show the root nodes and its direct children regardless of this setting. DOT_GRAPH_MAX_NODES = 50 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. # Warning: Depending on the platform used, enabling this option may lead to # badly anti-aliased labels on the edges of a graph (i.e. they become hard to # read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO openvpn-auth-ldap-auth-ldap-2.0.4/docs/resources/000077500000000000000000000000001332642612100216765ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/docs/resources/docbook.css000066400000000000000000000032141332642612100240300ustar00rootroot00000000000000/* * Stylesheet taken from the DarwinPorts Guide. * Contributed to the DarwinPorts project by Will Barton and Michael Maibaum. */ * { font-family: "Georgia", "Trebuchet MS"; } body { background: #c8dcff; width: 720px; margin: 15px auto 15px auto; font-size: 12px; line-height: 1.2; } a:link { color: #669; text-decoration: none; font-weight: bold; border-bottom: 1px dotted #c63; } a:visited { color: #888; text-decoration: none; font-weight: bold; border-bottom: 1px dotted #669; } a:hover { color: #c63; text-decoration: none; font-weight: bold; border-bottom: 1px dotted #369; } hr { display: none; } h3.title { color: #879880; margin: 1em 0 1em 0; padding: 0; border-bottom: 1px solid #ddd; } h4.title { color: #999; margin: 0 auto; padding: 0; } h5.title { color: #999; margin: 0 auto; padding: 0; } h1.title, h2.title { color: #669; margin: 5px 0 5px 0; padding: 10px 0 0 0; border-bottom: 1px solid #bbb; } .navheader, .navfooter, div.book, div.part, div.chapter, div.preface, div.sect1 { background: #fff; padding: 0.5em 2em; margin: 0.5em; border: 1px solid #bbb; } div.chapter div.sect1, div.preface div.sect1 { border: 0; padding: 0; margin: 0; } div.sect2, div.sect3 { margin: 0 1em; } pre.programlisting { color: #2F4F4F; background-color: #E6E6E6; font-family: "Courier New", Courier; font-weight: Bold; } .userinput { color: #669; } tt { font-family: "Courier New", Courier; } .filename, .computeroutput { color: #673; } .classname, .methodname, .varname, .term { color: #699; } .uri { font-family: "Courier New", Courier; font-weight: bold; } .database { color: #2F4F4F; } openvpn-auth-ldap-auth-ldap-2.0.4/docs/xml/000077500000000000000000000000001332642612100204645ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/docs/xml/auth-ldap.xml000066400000000000000000000023261332642612100230700ustar00rootroot00000000000000 OpenVPN Auth-LDAP: Enterprise LDAP Authentication for OpenVPN The content of this guide is the original work of Landon Fuller and Three Rings Design, Inc. All rights reserved. The XML and CSS used to generate this guide is based on the work of Will Barton and Michael Maibaum, as contributed to the DarwinPorts Project under the 3 clause BSD license. Their copyright remains. 2002 2003 2007 Landon Fuller >landonf@threerings.net< 2006 2007 Three Rings Design, Inc. 2002 2003 2004 The OpenDarwin Project About Auth-LDAP openvpn-auth-ldap-auth-ldap-2.0.4/framework.m4000066400000000000000000000043211332642612100211730ustar00rootroot00000000000000# From http://svn.saurik.com/repos/cycript/trunk/framework.m4 # # AC_CHECK_FRAMEWORK(FRAMEWORK, FUNCTION, # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], # [OTHER-LIBRARIES]) # ------------------------------------------------------ # # Use a cache variable name containing both the framework and function name, # because the test really is for framework $1 defining function $2, not # just for framework $1. Separate tests with the same $1 and different $2s # may have different results. # # Note that using directly AS_VAR_PUSHDEF([ac_Framework], [ac_cv_framework_$1_$2]) # is asking for troubles, since AC_CHECK_FRAMEWORK($framework, fun) would give # ac_cv_framework_$framework_fun, which is definitely not what was meant. Hence # the AS_LITERAL_IF indirection. # # FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, # whatever the FUNCTION, in addition to not being a *S macro. Note # that the cache does depend upon the function we are looking for. # # It is on purpose we used `ac_check_framework_save_LIBS' and not just # `ac_save_LIBS': there are many macros which don't want to see `LIBS' # changed but still want to use AC_CHECK_FRAMEWORK, so they save `LIBS'. # And ``ac_save_LIBS' is too tempting a name, so let's leave them some # freedom. AC_DEFUN([AC_CHECK_FRAMEWORK], [m4_ifval([$3], , [AH_CHECK_FRAMEWORK([$1])])dnl AS_LITERAL_IF([$1], [AS_VAR_PUSHDEF([ac_Framework], [ac_cv_framework_$1_$2])], [AS_VAR_PUSHDEF([ac_Framework], [ac_cv_framework_$1''_$2])])dnl AC_CACHE_CHECK([for $2 in $1 framework], ac_Framework, [ac_check_framework_save_LIBS=$LIBS LIBS="-framework $1 $5 $LIBS" AC_LINK_IFELSE([AC_LANG_CALL([], [$2])], [AS_VAR_SET(ac_Framework, yes)], [AS_VAR_SET(ac_Framework, no)]) LIBS=$ac_check_framework_save_LIBS]) AS_IF([test AS_VAR_GET(ac_Framework) = yes], [m4_default([$3], [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_FRAMEWORK_$1)) LIBS="-framework $1 $LIBS" ])], [$4])dnl AS_VAR_POPDEF([ac_Framework])dnl ])# AC_CHECK_FRAMEWORK # AH_CHECK_FRAMEWORK(FRAMEWORK) # --------------------- m4_define([AH_CHECK_FRAMEWORK], [AH_TEMPLATE(AS_TR_CPP(HAVE_FRAMEWORK_$1), [Define to 1 if you have the `]$1[' framework (-framework ]$1[).])]) openvpn-auth-ldap-auth-ldap-2.0.4/install-sh000077500000000000000000000112451332642612100207430ustar00rootroot00000000000000#! /bin/sh # # install - install a program, script, or datafile # This comes from X11R5. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. # # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 openvpn-auth-ldap-auth-ldap-2.0.4/mkinstalldirs000077500000000000000000000012341332642612100215420ustar00rootroot00000000000000#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" 1>&2 mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here openvpn-auth-ldap-auth-ldap-2.0.4/platform.m4000066400000000000000000000123321332642612100210230ustar00rootroot00000000000000 # This software is copyrighted by the Regents of the University of # California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState # Corporation and other parties. The following terms apply to all files # associated with the software unless explicitly disclaimed in # individual files. # # The authors hereby grant permission to use, copy, modify, distribute, # and license this software and its documentation for any purpose, provided # that existing copyright notices are retained in all copies and that this # notice is included verbatim in any distributions. No written agreement, # license, or royalty fee is required for any of the authorized uses. # Modifications to this software may be copyrighted by their authors # and need not follow the licensing terms described here, provided that # the new terms are clearly indicated on the first page of each file where # they apply. # # IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY # DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE # IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE # NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR # MODIFICATIONS. # # GOVERNMENT USE: If you are acquiring this software on behalf of the # U.S. government, the Government shall have only "Restricted Rights" # in the software and related documentation as defined in the Federal # Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you # are acquiring the software on behalf of the Department of Defense, the # software shall be classified as "Commercial Computer Software" and the # Government shall have only "Restricted Rights" as defined in Clause # 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the # authors grant the U.S. Government and others acting in its behalf # permission to use and distribute the software in accordance with the # terms specified in this license. #-------------------------------------------------------------------- # OD_CONFIG_PLUGIN # # Try to determine the proper flags to pass to the compiler # for building plugins. # # Arguments: # none # # Results: # # Defines and substitutes the following vars: # # MAKE_PLUGIN - Command to execute to build a plugin # INSTALL_PLUGIN - Command to execute to install a plugin # PLUGIN_CFLAGS - Flags to pass to cc when compiling the components # of a plugin (may request position-independent # code, among other things). # PLUGIN_LD - Base command to use for combining object files # into a plugin . # PLUGIN_LD_FLAGS -Flags to pass when building a plugin. This # differes from the PLUGIN_CFLAGS as it is not used # when building object files or executables. # PLUGIN_LD_LIBS - Dependent libraries for the linker to scan when # creating plugins. This symbol typically # goes at the end of the "ld" commands that build # plugins. The value of the symbol is # "${LIBS}" if all of the dependent libraries should # be specified when creating a plugin. If # dependent libraries should not be specified (as on # SunOS 4.x, where they cause the link to fail, or in # general if Tcl and Tk aren't themselves shared # libraries), then this symbol has an empty string # as its value. # PLUGIN_SUFFIX - Suffix to use for the names of dynamically loadable # extensions. An empty string means we don't know how # to use plugins on this platform. #-------------------------------------------------------------------- AC_DEFUN(OD_CONFIG_PLUGIN, [ LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" PLAT_OBJS="" case $host_os in rhapsody*|darwin*) PLUGIN_CFLAGS="-fno-common" PLUGIN_LD="cc -dynamiclib \${LDFLAGS}" PLUGIN_LD_FLAGS="" PLUGIN_SUFFIX=".dylib" ;; *) # A sensible default PLUGIN_CFLAGS="-fPIC" PLUGIN_LD="${CC} -shared" PLUGIN_LD_FLAGS="" PLUGIN_SUFFIX=".so" LDFLAGS="-export-dynamic" ;; esac if test "x$PLUGIN_SUFFIX" = "x" ; then AC_MSG_ERROR([Can't figure out how to do dynamic loading or plugins on this system.]) fi PLUGIN_FILE='${PLUGIN_NAME}${PLUGIN_SUFFIX}' MAKE_PLUGIN='${PLUGIN_LD} -o [$]@ ${PLUGIN_LD_FLAGS} ${PLUGIN_OBJS} ${LIBS}' INSTALL_PLUGIN='$(INSTALL_LIB) $(PLUGIN_FILE) $(PLUGIN_INSTALL_DIR)/$(PLUGIN_FILE)' CLEAN_PLUGIN='rm -f ${PLUGIN_FILE}' AC_SUBST(PLUGIN_LD) AC_SUBST(PLUGIN_LD_FLAGS) AC_SUBST(PLUGIN_CFLAGS) AC_SUBST(PLUGIN_SUFFIX) AC_SUBST(PLUGIN_FILE) AC_SUBST(MAKE_PLUGIN) AC_SUBST(INSTALL_PLUGIN) AC_SUBST(CLEAN_PLUGIN) ]) openvpn-auth-ldap-auth-ldap-2.0.4/pthread.m4000066400000000000000000000221171332642612100206300ustar00rootroot00000000000000dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) dnl dnl Modified from the original version: dnl * Removed pthread-specific CC support dnl * Added FreeBSD specific -pthread/-lpthread flags dnl * When setting flags, set them for both LIBS and CFLAGS dnl Notes: dnl * -D_THREAD_SAFE may not be necessary on FreeBSD dnl and elsewhere. dnl - landonf March 25th, 2005 dnl dnl This macro figures out how to build C programs using POSIX threads. dnl It sets the PTHREAD_LIBS output variable to the threads library and dnl linker flags, and the PTHREAD_CFLAGS output variable to any special dnl C compiler flags that are needed. (The user can also force certain dnl compiler flags/libs to be tested by setting these environment dnl variables.) dnl dnl NOTE: You are assumed to not only compile your program with these dnl flags, but also link it with them as well. e.g. you should link dnl with $CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS dnl $LIBS dnl dnl If you are only building threads programs, you may wish to use dnl these variables in your default LIBS, and CFLAGS: dnl dnl LIBS="$PTHREAD_LIBS $LIBS" dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS" dnl dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). dnl dnl ACTION-IF-FOUND is a list of shell commands to run if a threads dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the dnl default action will define HAVE_PTHREAD. dnl dnl Please let the authors know if this macro fails on any platform, or dnl if you have any other suggestions or comments. This macro was based dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros dnl posted by Alejandro Forero Cuervo to the autoconf macro repository. dnl We are also grateful for the helpful feedback of numerous users. dnl dnl @category InstalledPackages dnl @author Steven G. Johnson dnl @version 2005-01-14 dnl @license GPLWithACException AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthread or # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" ;; *freebsd*) # freebsd 4 uses -pthread, freebsd 5 uses -lpthread acx_pthread_flags="pthread -pthread" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" PTHREAD_LIBS="$flag" ;; pthread-config) AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_TRY_LINK([#include ], [int attr=$attr;], [attr_name=$attr; break]) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl ACX_PTHREAD openvpn-auth-ldap-auth-ldap-2.0.4/regen.sh000077500000000000000000000000371332642612100203730ustar00rootroot00000000000000#!/bin/sh autoconf autoheader openvpn-auth-ldap-auth-ldap-2.0.4/src/000077500000000000000000000000001332642612100175235ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/src/Makefile.in000077500000000000000000000034161332642612100215770ustar00rootroot00000000000000srcdir= @srcdir@ top_srcdir= @top_srcdir@ top_builddir= @top_builddir@ VPATH= @srcdir@ include ${top_builddir}/Mk/autoconf.mk include ${top_builddir}/Mk/compile.mk include ${top_builddir}/Mk/subdir.mk PLUGIN_NAME= openvpn-auth-ldap PLUGIN_OBJS= auth-ldap.o AUTH_LIB= libauth-ldap.a AUTH_OBJS= TRArray.o \ TRAutoreleasePool.o \ TRConfig.o \ TRConfigLexer.o \ TRConfigParser.o \ TRConfigToken.o \ TRAuthLDAPConfig.o \ TREnumerator.o \ TRHash.o \ TRLDAPAccountRepository.o \ TRLDAPConnection.o \ TRLDAPEntry.o \ TRLDAPGroupConfig.o \ TRLDAPSearchFilter.o \ TRLocalPacketFilter.o \ TRLog.o \ TRObject.o \ TRPFAddress.o \ TRPacketFilter.o \ TRString.o \ TRVPNSession.o \ hash.o \ strlcpy.o \ xmalloc.o \ base64.o \ openvpn-cr.o GEN_SRCS= TRConfigParser.m \ TRConfigParser.h \ TRConfigLexer.m TEST_OBJS= testplugin.o CFLAGS+= $(LDAP_CFLAGS) $(OPENVPN_CFLAGS) OBJCFLAGS+= $(LDAP_CFLAGS) $(OPENVPN_CFLAGS) LIBS+= -L. -lauth-ldap \ $(LDAP_LIBS) \ $(OBJC_LIBS) \ $(FLEX_LIBS) INSTALL_LIB= $(INSTALL) -m 755 PLUGIN_INSTALL_DIR= $(DESTDIR)$(libdir) all:: $(PLUGIN_FILE) $(AUTH_LIB) testplugin # Work-around for gnumake bug. # It fails to check if 'TRConfigParser.h' has been created # after lemon has been called, and goes looking for a # rule to build it. TRConfigParser.h: TRConfigParser.m $(PLUGIN_FILE): $(AUTH_LIB) $(PLUGIN_OBJS) $(MAKE_PLUGIN) $(AUTH_LIB): $(GEN_SRCS) $(AUTH_OBJS) $(AR) -r $@ $(AUTH_OBJS) testplugin:: $(TEST_OBJS) $(PLUGIN_OBJS) $(AUTH_LIB) $(CC) -o $@ ${TEST_OBJS} ${PLUGIN_OBJS} ${LDFLAGS} ${LIBS} install:: $(PLUGIN_FILE) $(INSTALL_PLUGIN) clean:: rm -f $(AUTH_OBJS) $(TEST_OBJS) $(PLUGIN_OBJS) $(AUTH_LIB) $(GEN_SRCS) testplugin $(CLEAN_PLUGIN) distclean:: clean rm -f Makefile openvpn-auth-ldap-auth-ldap-2.0.4/src/PXObjCRuntime.h000066400000000000000000000040451332642612100223300ustar00rootroot00000000000000/* * PXObjCRuntime.h vi:ts=4:sw=4:expandtab: * * Author: Landon Fuller * * Copyright (c) 2007 - 2012 Landon Fuller * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import /** Used to describe a signed integer */ #if __LP64__ typedef long PXInteger; #else typedef int PXInteger; #endif /** Used to describe an unsigned integer */ #if __LP64__ typedef unsigned long PXUInteger; #else typedef unsigned int PXUInteger; #endif openvpn-auth-ldap-auth-ldap-2.0.4/src/TRAccountRepository.h000066400000000000000000000044301332642612100236370ustar00rootroot00000000000000/* * TRAccountRepository.h vi:ts=4:sw=4:expandtab: * * Author: Landon Fuller * * Copyright (c) 2008 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef TRACCOUNTREPOSITORY_H #define TRACCOUNTREPOSITORY_H /** * Intentionally simple user/group account verification. */ @protocol TRAccountRepository /** * Authenticate a user with the provided username and password. * Return YES if authentication succeeds, NO on failure. */ - (BOOL) authenticateUser: (TRString *) username withPassword: (TRString *) password; /** * Check if the given username is a member of a group. * Return YES if the user is a member, or NO on failure. */ - (BOOL) checkGroupMember: (TRString *) username withGroup: (TRString *) groupname; @end #endif /* TRACCOUNTREPOSITORY_H */ openvpn-auth-ldap-auth-ldap-2.0.4/src/TRArray.h000066400000000000000000000041221332642612100212170ustar00rootroot00000000000000/* * TRArray.h vi:ts=4:sw=4:expandtab: * Simple linked list * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRObject.h" #import "TREnumerator.h" @interface TRArray : TRObject { @private unsigned int _count; struct _TRArrayStack *_stack; struct _TRArrayStack *_stackBottom; } - (void) addObject: (id) anObject; - (void) removeObject; - (id) lastObject; - (BOOL) containsObject: (id) anObject; - (TREnumerator *) objectEnumerator; - (TREnumerator *) objectReverseEnumerator; - (unsigned int) count; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRArray.m000066400000000000000000000147401332642612100212330ustar00rootroot00000000000000/* * TRArray.m vi:ts=4:sw=4:expandtab: * Simple linked list * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import "TRArray.h" #import "xmalloc.h" typedef struct _TRArrayStack { id object; struct _TRArrayStack *prev; struct _TRArrayStack *next; } TRArrayStack; /** * Array enumerator. */ @interface TRArrayObjectEnumerator : TREnumerator { TRArray *_array; TRArrayStack *_stack; } - (id) initWithArray: (TRArray *) array; @end /** * Reverse array enumerator. */ @interface TRArrayReverseObjectEnumerator : TRArrayObjectEnumerator @end /* * We need to declare prototypes for our private methods, as some * versions of gcc won't pick them up from the implementation. */ @interface TRArray (TRArrayPrivate) - (TRArrayStack *) _privateArrayContext: (BOOL) top; @end /** * A simple array implementation, provides forward and reverse * enumerators. */ @implementation TRArray - (id) init { self = [super init]; if (!self) return self; _count = 0; /* Initialize our linked list */ _stack = xmalloc(sizeof(TRArrayStack)); _stack->object= nil; _stack->next = NULL; _stack->prev= NULL; _stackBottom = _stack; return self; } - (void) dealloc { TRArrayStack *node; /* Clean up our stack */ for (node = _stack; _stack; node = _stack) { /* Release the associated object */ [node->object release]; _stack = node->next; free(node); } [super dealloc]; } - (unsigned int) count { return _count; } /** * Add anObject to the array. * @param anObject: Object to add; */ - (void) addObject: (id) anObject { TRArrayStack *node; /* Allocate, initialize, and push the new node on to the stack */ node = xmalloc(sizeof(TRArrayStack)); node->object = [anObject retain]; node->prev = NULL; node->next = _stack; _stack->prev = node; _stack = node; _count++; } /** * Remove top-most object from the array (LIFO). */ - (void) removeObject { TRArrayStack *node; /* Pop the stack */ node = _stack; _stack = _stack->next; _stack->prev = NULL; /* Dealloc the removed node */ [node->object release]; free(node); _count--; } /** * Return the last object added to the array. * @return Last object added to the array. */ - (id) lastObject { /* Return the last object on the stack */ return _stack->object; } /** * Test if the array contains anObject. * Implemented by calling isEqual on all objects in the array. * @param anObject: Object to test for equality. * @return YES if the array contains anObject, NO otherwise. */ - (BOOL) containsObject: (id) anObject { TRArrayStack *node; /* Anything claim to be equal with anObject? */ for (node = _stack; node; node = node->next) { if ([node->object isEqual: anObject]) return YES; } return NO; } - (TRArrayStack *) _privateArrayContext: (BOOL) top { if (top) return _stack; else return _stackBottom; } /** * Return a object enumerator. * This enumerater walks the stack, * implementing a LIFO interface. * * Due to our lack of an autorelease pool, * it is the caller's responsibility to release * the returned value. */ - (TREnumerator *) objectEnumerator { return [[[TRArrayObjectEnumerator alloc] initWithArray: self] autorelease]; } /** * Return a object enumerator. * This enumerater walks the stack in reverse, * implementing a FIFO interface. * * Due to our lack of an autorelease pool, * it is the caller's responsibility to release * the returned value. */ - (TREnumerator *) objectReverseEnumerator { return [[[TRArrayReverseObjectEnumerator alloc] initWithArray: self] autorelease]; } @end /* TRArray */ @implementation TRArrayObjectEnumerator - (void) dealloc { [_array release]; [super dealloc]; } - (id) initWithArray: (TRArray *) array { self = [super init]; if (!self) return self; _array = [array retain]; _stack = [array _privateArrayContext: YES]; return self; } - (id) nextObject { TRArrayStack *next; if (!_stack) return nil; /* Pop the next node from the stack */ next = _stack; _stack = _stack->next; /* Return the next node */ return (next->object); } @end /* TRArrayObjectEnumerator */ @implementation TRArrayReverseObjectEnumerator - (id) initWithArray: (TRArray *) array { self = [super init]; if (!self) return self; /* We want the bottom-most element of the stack, * skipping the NULL terminator */ _stack = [array _privateArrayContext: NO]->prev; return self; } - (id) nextObject { TRArrayStack *prev; if (!_stack) return nil; /* Walk the stack in reverse */ prev = _stack; _stack = _stack->prev; /* Return the previous node */ return (prev->object); } @end /* TRArrayObjectEnumerator */ openvpn-auth-ldap-auth-ldap-2.0.4/src/TRAuthLDAPConfig.h000066400000000000000000000100471332642612100226340ustar00rootroot00000000000000/* * TRAuthLDAPConfig.h vi:ts=4:sw=4:expandtab: * Simple Configuration * * Copyright (c) 2005 - 2007 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRObject.h" #import "TRLDAPGroupConfig.h" #import "TRConfig.h" #import "TRString.h" #import "TRArray.h" @interface TRAuthLDAPConfig : TRObject { @private /* LDAP Settings */ TRString *_url; BOOL _tlsEnabled; BOOL _referralEnabled; int _timeout; TRString *_tlsCACertFile; TRString *_tlsCACertDir; TRString *_tlsCertFile; TRString *_tlsKeyFile; TRString *_tlsCipherSuite; TRString *_bindDN; TRString *_bindPassword; /* Authentication / Authorization Settings */ TRString *_baseDN; TRString *_searchFilter; BOOL _requireGroup; TRString *_pfTable; TRArray *_ldapGroups; BOOL _pfEnabled; BOOL _passwordISCR; /* Parser State */ TRString *_configFileName; TRConfig *_configDriver; TRArray *_sectionStack; } - (id) initWithConfigFile: (const char *) fileName; /* TRConfigDelegate */ - (void) setKey: (TRConfigToken *) key value: (TRConfigToken *) value; - (void) startSection: (TRConfigToken *) sectionType sectionName: (TRConfigToken *) name; - (void) endSection: (TRConfigToken *) sectionEnd; - (void) parseError: (TRConfigToken *) badToken; /* Accessors */ - (TRString *) url; - (void) setURL: (TRString *) newURL; - (int) timeout; - (void) setTimeout: (int) newTimeout; - (BOOL) tlsEnabled; - (void) setTLSEnabled: (BOOL) newTLSSetting; - (TRString *) tlsCACertFile; - (void) setTLSCACertFile: (TRString *) fileName; - (TRString *) tlsCACertDir; - (void) setTLSCACertDir: (TRString *) directoryName; - (TRString *) tlsCertFile; - (void) setTLSCertFile: (TRString *) newFilename; - (TRString *) tlsKeyFile; - (void) setTLSKeyFile: (TRString *) fileName; - (TRString *) tlsCipherSuite; - (void) setTLSCipherSuite: (TRString *) cipherSuite; - (TRString *) bindDN; - (void) setBindDN: (TRString *) bindDN; - (TRString *) bindPassword; - (void) setBindPassword: (TRString *) bindPassword; - (TRString *) baseDN; - (void) setBaseDN: (TRString *) baseDN; - (TRString *) searchFilter; - (void) setSearchFilter: (TRString *) searchFilter; - (BOOL) referralEnabled; - (void) setReferralEnabled: (BOOL) newReferralSetting; - (BOOL) requireGroup; - (void) setRequireGroup: (BOOL) requireGroup; - (TRString *) pfTable; - (void) setPFTable: (TRString *) tableName; - (BOOL) pfEnabled; - (void) setPFEnabled: (BOOL) newPFSetting; - (TRArray *) ldapGroups; - (BOOL) passWordIsCR; - (void) setPassWordIsCR: (BOOL)newCRSetting; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRAuthLDAPConfig.m000066400000000000000000000722371332642612100226520ustar00rootroot00000000000000/* * TRAuthLDAPConfig.m vi:ts=4:sw=4:expandtab: * Simple Configuration * * Copyright (c) 2005 - 2007 Landon Fuller * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import #import #import #import #import #import "TRAuthLDAPConfig.h" #import "TRLog.h" #import "TRHash.h" /* All Variables and Section Types */ typedef enum { /* All Section Types */ LF_NO_SECTION, /* Top-level */ LF_LDAP_SECTION, /* LDAP Server Settings */ LF_AUTH_SECTION, /* LDAP Authorization Settings */ LF_GROUP_SECTION, /* LDAP Group Settings */ /* Generic LDAP Search Variables */ LF_LDAP_BASEDN, /* Base DN for Search */ LF_LDAP_SEARCH_FILTER, /* Search Filter */ /* Generic PF Variables */ LF_AUTH_PFTABLE, /* PF Table Name */ /* LDAP Section Variables */ LF_LDAP_URL, /* LDAP Server URL */ LF_LDAP_TIMEOUT, /* LDAP Server Timeout */ LF_LDAP_BINDDN, /* Bind DN for LDAP Searches */ LF_LDAP_PASSWORD, /* Associated Password */ LF_LDAP_REFERRAL, /* Enable Referrals */ LF_LDAP_TLS, /* Enable TLS */ LF_LDAP_TLS_CA_CERTFILE, /* TLS CA Certificate File */ LF_LDAP_TLS_CA_CERTDIR, /* TLS CA Certificate Dir */ LF_LDAP_TLS_CERTFILE, /* TLS Client Certificate File */ LF_LDAP_TLS_KEYFILE, /* TLS Client Key File */ LF_LDAP_TLS_CIPHER_SUITE, /* TLS Cipher Suite */ /* Authorization Section Variables */ LF_AUTH_REQUIRE_GROUP, /* Require Group Membership */ /* Group Section Variables */ LF_GROUP_MEMBER_ATTRIBUTE, /* Group Membership Attribute */ LF_GROUP_MEMBER_RFC2307BIS, /* Look for full DN for user in attribute */ LF_GROUP_MEMBER_USECOMPAREOPERATION, /* Use LDAP Compare operation instead of Search (Search is faster but doesn't work in all LDAP environments) */ /* OpenVPN Challenge/Response */ LF_AUTH_PASSWORD_CR, /* Password is in challenge/repsonse format */ /* Misc Shared */ LF_UNKNOWN_OPCODE, /* Unknown Opcode */ } ConfigOpcode; typedef struct OpcodeTable { const char *name; ConfigOpcode opcode; BOOL multi; BOOL required; } OpcodeTable; /* Bad opcode */ static OpcodeTable UnknownOpcode = { .name = "", .opcode = LF_UNKNOWN_OPCODE, .multi = NO, .required = NO }; /* Section Types */ static OpcodeTable SectionTypes[] = { /* name opcode multi required */ { "LDAP", LF_LDAP_SECTION, NO, YES }, { "Authorization", LF_AUTH_SECTION, NO, YES }, { "Group", LF_GROUP_SECTION, YES, NO }, { NULL, 0 } }; /* Generic LDAP Search Variables */ static OpcodeTable GenericLDAPVariables[] = { /* name opcode multi required */ { "BaseDN", LF_LDAP_BASEDN, NO, YES }, { "SearchFilter", LF_LDAP_SEARCH_FILTER, NO, YES }, { NULL, 0 } }; /* Generic PF Table Variables */ static OpcodeTable GenericPFVariables[] = { #ifdef HAVE_PF /* name opcode multi required */ { "PFTable", LF_AUTH_PFTABLE, NO, NO }, #endif { NULL, 0 } }; /* LDAP Section Variables */ static OpcodeTable LDAPSectionVariables[] = { /* name opcode multi required */ { "URL", LF_LDAP_URL, NO, YES }, { "Timeout", LF_LDAP_TIMEOUT, NO, NO }, { "BindDN", LF_LDAP_BINDDN, NO, NO }, { "Password", LF_LDAP_PASSWORD, NO, NO }, { "FollowReferrals", LF_LDAP_REFERRAL, NO, NO }, { "TLSEnable", LF_LDAP_TLS, NO, NO }, { "TLSCACertFile", LF_LDAP_TLS_CA_CERTFILE, NO, NO }, { "TLSCACertDir", LF_LDAP_TLS_CA_CERTDIR, NO, NO }, { "TLSCertFile", LF_LDAP_TLS_CERTFILE, NO, NO }, { "TLSKeyFile", LF_LDAP_TLS_KEYFILE, NO, NO }, { "TLSCipherSuite", LF_LDAP_TLS_CIPHER_SUITE, NO, NO }, { NULL, 0 } }; /* Authorization Section Variables */ static OpcodeTable AuthSectionVariables[] = { /* name opcode multi required */ { "RequireGroup", LF_AUTH_REQUIRE_GROUP, NO, NO }, { NULL, 0} }; /* Group Section Variables */ static OpcodeTable GroupSectionVariables[] = { /* name opcode multi required */ { "MemberAttribute", LF_GROUP_MEMBER_ATTRIBUTE, NO, NO }, { "RFC2307bis", LF_GROUP_MEMBER_RFC2307BIS, NO, NO }, { "UseCompareOperation", LF_GROUP_MEMBER_USECOMPAREOPERATION, NO, NO }, { NULL, 0 } }; /* OpenVPN Challenge/Response */ static OpcodeTable OpenVPNCRVariables[] = { /* name opcode multi required */ { "PasswordIsCR", LF_AUTH_PASSWORD_CR, NO, NO }, { NULL, 0 } }; /* Section Types */ static OpcodeTable *Sections[] = { SectionTypes, NULL }; /* LDAP Section Definition */ static OpcodeTable *LDAPSection[] = { LDAPSectionVariables, NULL }; /* Auth Section Definition */ static OpcodeTable *AuthSection[] = { AuthSectionVariables, GenericLDAPVariables, GenericPFVariables, OpenVPNCRVariables, NULL }; /* Group Section Definition */ static OpcodeTable *GroupSection[] = { GroupSectionVariables, GenericLDAPVariables, GenericPFVariables, NULL }; /* Parse a string, returning the associated entry from the supplied table */ static OpcodeTable *parse_opcode (TRConfigToken *token, OpcodeTable **tables) { const char *cp = [token cString]; OpcodeTable *table, **p; unsigned int i; for (p = tables; *p; p++) { table = *p; for (i = 0; table[i].name; i++) if (strcasecmp(cp, table[i].name) == 0) return (&table[i]); } /* Unknown opcode */ return (&UnknownOpcode); } /* Parse a string, returning the associated opcode from the supplied table */ static const char *string_for_opcode(ConfigOpcode opcode, OpcodeTable *tables[]) { OpcodeTable *table, **p; unsigned int i; for (p = tables; *p; p++) { table = *p; for (i = 0; table[i].name; i++) if (table[i].opcode == opcode) return (table[i].name); } /* Unknown opcode */ return ("?"); } /* * Simple object that maintains section parsing state */ @interface SectionState : TRObject { ConfigOpcode _opcode; TRHash *_hash; id _context; } @end @implementation SectionState - (void) dealloc { [_hash release]; if (_context) [_context release]; [super dealloc]; } - (id) init { self = [super init]; if (!self) return self; _opcode = LF_UNKNOWN_OPCODE; _hash = [[TRHash alloc] initWithCapacity: HASHCOUNT_T_MAX]; return self; } - (id) initWithOpcode: (ConfigOpcode) anOpcode { if ([self init]) _opcode = anOpcode; return self; } - (ConfigOpcode) opcode { return _opcode; } - (TRHash *) hashTable { return _hash; } - (void) setContext: (id) context { if (_context) [_context release]; _context = [context retain]; } - (id) context { return _context; } @end /** * Handles parsing of the plugin configuration file. */ @implementation TRAuthLDAPConfig - (void) dealloc { if (_url) [_url release]; if (_bindDN) [_bindDN release]; if (_bindPassword) [_bindPassword release]; if (_tlsCACertFile) [_tlsCACertFile release]; if (_tlsCACertDir) [_tlsCACertDir release]; if (_tlsCertFile) [_tlsCertFile release]; if (_tlsKeyFile) [_tlsKeyFile release]; if (_tlsCipherSuite) [_tlsCipherSuite release]; if (_baseDN) [_baseDN release]; if (_searchFilter) [_searchFilter release]; if (_ldapGroups) [_ldapGroups release]; if (_pfTable) [_pfTable release]; [super dealloc]; } /** * Initialize with the provided configuration file path. * The file will be parsed, and if an error occurs, * NULL returned. */ - (id) initWithConfigFile: (const char *) fileName { SectionState *section; int configFD; /* Initialize */ self = [self init]; if (self == NULL) return (self); /* Initialize the section stack */ _sectionStack = [[TRArray alloc] init]; section = [[SectionState alloc] initWithOpcode: LF_NO_SECTION]; [_sectionStack addObject: section]; [section release]; /* Open our configuration file */ _configFileName = [[TRString alloc] initWithCString: fileName]; configFD = open(fileName, O_RDONLY); if (configFD == -1) { [TRLog error: "Failed to open \"%s\" for reading", [_configFileName cString]]; goto error; } /* Initialize the config parser */ _configDriver = [[TRConfig alloc] initWithFD: configFD configDelegate: self]; if (_configDriver == NULL) goto error; /* Parse the configuration file */ if (![_configDriver parseConfig]) goto error; [_configDriver release]; [_sectionStack release]; [_configFileName release]; return self; error: if (_configDriver) [_configDriver release]; if (_sectionStack) [_sectionStack release]; if (_configFileName) [_configFileName release]; [self release]; return (NULL); } /** * Return the current section opcode from the top * of the section stack. */ - (ConfigOpcode) currentSectionOpcode { return [[_sectionStack lastObject] opcode]; } /** * Return the current section's hash table. */ - (TRHash *) currentSectionHashTable { return [[_sectionStack lastObject] hashTable]; } /** * Return the current section's context. */ - (id) currentSectionContext { return [[_sectionStack lastObject] context]; } /** * Set the current section's context. */ - (void) setCurrentSectionContext: (id) context { [[_sectionStack lastObject] setContext: context]; } /** * Allocate a SectionState object and push it onto the * section stack. */ - (void) pushSection: (ConfigOpcode) opcode { SectionState *section; section = [[SectionState alloc] initWithOpcode: opcode]; [_sectionStack addObject: section]; [section release]; } /** * Report a named section that should not be named to the user. */ - (void) errorNamedSection: (TRConfigToken *) section withName: (TRConfigToken *) name { [TRLog error: "Auth-LDAP Configuration Error: %s section types must be unnamed (%s:%u).", [section cString], [_configFileName cString], [name lineNumber]]; [_configDriver errorStop]; } /** * Report an unknown key to the user. */ - (void) errorUnknownKey: (TRConfigToken *) key { [TRLog error: "Auth-LDAP Configuration Error: %s key is unknown (%s:%u).", [key cString], [_configFileName cString], [key lineNumber]]; [_configDriver errorStop]; } /** * Report a duplicate key to the user. */ - (void) errorMultiKey: (TRConfigToken *) key { [TRLog error: "Auth-LDAP Configuration Error: multiple occurances of key %s (%s:%u).", [key cString], [_configFileName cString], [key lineNumber]]; [_configDriver errorStop]; } /** * Report an invalid integer value to the user. */ - (void) errorIntValue: (TRConfigToken *) value { [TRLog error: "Auth-LDAP Configuration Error: %s value is not an integer (%s:%u).", [value cString], [_configFileName cString], [value lineNumber]]; [_configDriver errorStop]; } /** * Report an invalid boolean value to the user. */ - (void) errorBoolValue: (TRConfigToken *) value { [TRLog error: "Auth-LDAP Configuration Error: %s value is not a boolean value -- use either 'True' or 'False' (%s:%u).", [value cString], [_configFileName cString], [value lineNumber]]; [_configDriver errorStop]; } /** * Report an unknown section type to the user. */ - (void) errorUnknownSection: (TRConfigToken *) section { [TRLog error: "Auth-LDAP Configuration Error: %s is not a known section type within this context (%s:%u).", [section cString], [_configFileName cString], [section lineNumber]]; [_configDriver errorStop]; } /** * Report mismatched section closure to the user. */ - (void) errorMismatchedSection: (TRConfigToken *) section { [TRLog error: "Auth-LDAP Configuration Error: '' is a mismatched section closure. Expected \"\" (%s:%u).", [section cString], string_for_opcode([self currentSectionOpcode], Sections), [_configFileName cString], [section lineNumber]]; [_configDriver errorStop]; } /** * Check for any missing required variables and report them to the user. * @return YES on success, NO on failure. */ - (BOOL) validateRequiredVariables: (OpcodeTable **) tables withSectionEnd: (TRConfigToken *) section { OpcodeTable *table, **p; unsigned int i; for (p = tables; *p; p++) { table = *p; for (i = 0; table[i].name; i++) { if (table[i].required) { TRString *key = [[TRString alloc] initWithCString: table[i].name]; if ([[self currentSectionHashTable] valueForKey: key] == nil) { [TRLog error: "Auth-LDAP Configuration Error: Section %s is a missing required key '%s' (%s:%u).", string_for_opcode([self currentSectionOpcode], Sections), table[i].name, [_configFileName cString], [section lineNumber]]; [key release]; [_configDriver errorStop]; return NO; } [key release]; } } } return YES; } /** * Called by the lemon generated parser when a new section is found. */ - (void) startSection: (TRConfigToken *) sectionType sectionName: (TRConfigToken *) name { OpcodeTable *opcodeEntry; /* Parse the section opcode */ opcodeEntry = parse_opcode(sectionType, Sections); /* Enter handler for the current state */ switch([self currentSectionOpcode]) { /* Top-level sections supported: * - LDAP (unnamed) * - Group (named) */ case LF_NO_SECTION: switch (opcodeEntry->opcode) { case LF_LDAP_SECTION: if (name) { [self errorNamedSection: sectionType withName: name]; return; } [self pushSection: opcodeEntry->opcode]; break; case LF_AUTH_SECTION: if (name) { [self errorNamedSection: sectionType withName: name]; return; } [self pushSection: opcodeEntry->opcode]; break; default: [self errorUnknownSection: sectionType]; return; } break; case LF_AUTH_SECTION: /* Currently, no named sections are supported */ if (name) { [self errorNamedSection: sectionType withName: name]; return; } /* Validate the section type */ switch (opcodeEntry->opcode) { TRLDAPGroupConfig *groupConfig; case LF_GROUP_SECTION: groupConfig = [[TRLDAPGroupConfig alloc] init]; [self pushSection: opcodeEntry->opcode]; [self setCurrentSectionContext: groupConfig]; if (!_ldapGroups) { _ldapGroups = [[TRArray alloc] init]; } /* Let the SectionContext own groupConfig */ [groupConfig release]; break; default: [self errorUnknownSection: sectionType]; return; } break; default: [self errorUnknownSection: sectionType]; return; } return; } /** * Called by the lemon-generated parser when a key value pair is found. */ - (void) setKey: (TRConfigToken *) key value: (TRConfigToken *) value { /* Handle key value pairs */ OpcodeTable *opcodeEntry; TRHash *hashTable = [self currentSectionHashTable]; switch ([self currentSectionOpcode]) { case LF_NO_SECTION: /* No keys are permitted in the top-level */ [self errorUnknownKey: key]; return; case LF_LDAP_SECTION: opcodeEntry = parse_opcode(key, LDAPSection); if (!opcodeEntry) { [self errorUnknownKey: key]; return; } switch (opcodeEntry->opcode) { int timeout; BOOL enableTLS; BOOL enableReferral; /* LDAP URL */ case LF_LDAP_URL: [self setURL: [value string]]; break; /* LDAP Bind DN */ case LF_LDAP_BINDDN: [self setBindDN: [value string]]; break; /* LDAP Bind Password */ case LF_LDAP_PASSWORD: [self setBindPassword: [value string]]; break; /* LDAP Connection Timeout */ case LF_LDAP_TIMEOUT: if (![value intValue: &timeout]) { [self errorIntValue: value]; return; } [self setTimeout: timeout]; break; /* LDAP Referrals Enabled */ case LF_LDAP_REFERRAL: if (![value boolValue: &enableReferral]) { [self errorBoolValue: value]; return; } [self setReferralEnabled: enableReferral]; break; /* LDAP TLS Enabled */ case LF_LDAP_TLS: if (![value boolValue: &enableTLS]) { [self errorBoolValue: value]; return; } [self setTLSEnabled: enableTLS]; break; /* LDAP CA Certificate */ case LF_LDAP_TLS_CA_CERTFILE: [self setTLSCACertFile: [value string]]; break; /* LDAP CA Certificate Directory */ case LF_LDAP_TLS_CA_CERTDIR: [self setTLSCACertDir: [value string]]; break; /* LDAP Certificate File */ case LF_LDAP_TLS_CERTFILE: [self setTLSCertFile: [value string]]; break; /* LDAP Key File */ case LF_LDAP_TLS_KEYFILE: [self setTLSKeyFile: [value string]]; break; /* TLS Cipher Suite */ case LF_LDAP_TLS_CIPHER_SUITE: [self setTLSCipherSuite: [value string]]; break; /* Unknown Setting */ default: [self errorUnknownKey: key]; return; } break; case LF_AUTH_SECTION: opcodeEntry = parse_opcode(key, AuthSection); if (!opcodeEntry) { [self errorUnknownKey: key]; return; } switch(opcodeEntry->opcode) { BOOL requireGroup; BOOL passWordCR; case LF_AUTH_REQUIRE_GROUP: if (![value boolValue: &requireGroup]) { [self errorBoolValue: value]; return; } [self setRequireGroup: requireGroup]; break; case LF_LDAP_BASEDN: [self setBaseDN: [value string]]; break; case LF_LDAP_SEARCH_FILTER: [self setSearchFilter: [value string]]; break; case LF_AUTH_PFTABLE: [self setPFTable: [value string]]; [self setPFEnabled: YES]; break; case LF_AUTH_PASSWORD_CR: if (![value boolValue: &passWordCR]) { [self errorBoolValue: value]; return; } [self setPassWordIsCR: passWordCR]; break; /* Unknown Setting */ default: [self errorUnknownKey: key]; return; } break; case LF_GROUP_SECTION: opcodeEntry = parse_opcode(key, GroupSection); if (!opcodeEntry) { [self errorUnknownKey: key]; return; } switch(opcodeEntry->opcode) { TRLDAPGroupConfig *config; BOOL memberRFC2307BIS; BOOL useCompareOperation; case LF_GROUP_MEMBER_ATTRIBUTE: config = [self currentSectionContext]; [config setMemberAttribute: [value string]]; break; case LF_GROUP_MEMBER_RFC2307BIS: config = [self currentSectionContext]; if (![value boolValue: &memberRFC2307BIS]) { [self errorBoolValue: value]; return; } [config setMemberRFC2307BIS: memberRFC2307BIS]; break; case LF_GROUP_MEMBER_USECOMPAREOPERATION: config = [self currentSectionContext]; if (![value boolValue: &useCompareOperation]) { [self errorBoolValue: value]; return; } [config setUseCompareOperation: useCompareOperation]; break; case LF_LDAP_BASEDN: config = [self currentSectionContext]; [config setBaseDN: [value string]]; break; case LF_LDAP_SEARCH_FILTER: config = [self currentSectionContext]; [config setSearchFilter: [value string]]; break; case LF_AUTH_PFTABLE: config = [self currentSectionContext]; [config setPFTable: [value string]]; [self setPFEnabled: YES]; break; /* Unknown Setting */ default: [self errorUnknownKey: key]; } break; default: /* Must be unreachable! */ [TRLog error: "Unhandled section type in setKey!\n"]; abort(); break; } /* Lastly, prevent multiple occurances of a single-use key */ if (!opcodeEntry->multi) { if ([hashTable valueForKey: [key string]]) { [self errorMultiKey: key]; return; } [hashTable setObject: value forKey: [key string]]; } } /** * Verify that the now closed section isn't mismatched, and then pop it off * the section stack. */ - (void) endSection: (TRConfigToken *) sectionEnd { OpcodeTable *opcodeEntry; opcodeEntry = parse_opcode(sectionEnd, Sections); /* Mismatched section? */ if (!opcodeEntry || opcodeEntry->opcode != [self currentSectionOpcode]) { [self errorMismatchedSection: sectionEnd]; return; } switch (opcodeEntry->opcode) { case LF_LDAP_SECTION: [self validateRequiredVariables: LDAPSection withSectionEnd: sectionEnd]; break; case LF_AUTH_SECTION: [self validateRequiredVariables: AuthSection withSectionEnd: sectionEnd]; break; case LF_GROUP_SECTION: /* Add the group config to the array */ if (![self validateRequiredVariables: GroupSection withSectionEnd: sectionEnd]) break; [_ldapGroups addObject: [self currentSectionContext]]; break; default: /* Must be unreachable! */ [TRLog error: "Unhandled section type in endSection!\n"]; abort(); return; } [_sectionStack removeObject]; } - (void) parseError: (TRConfigToken *) badToken { if (badToken) [TRLog error: "A parse error occured while attempting to comprehend %s, on line %u.", [badToken cString], [badToken lineNumber]]; else [TRLog error: "A parse error occured while attempting to read your configuration file."]; [_configDriver errorStop]; } /* Accessors */ - (BOOL) tlsEnabled { return (_tlsEnabled); } - (void) setTLSEnabled: (BOOL) newTLSSetting { _tlsEnabled = newTLSSetting; } - (TRString *) url { return (_url); } - (TRString *) bindDN { return (_bindDN); } - (void) setBindDN: (TRString *) bindDN { if (_bindDN) [_bindDN release]; _bindDN = [bindDN retain]; } - (TRString *) bindPassword { return (_bindPassword); } - (void) setBindPassword: (TRString *) bindPassword { if (_bindPassword) [_bindPassword release]; _bindPassword = [bindPassword retain]; } - (void) setURL: (TRString *) newURL { if (_url) [_url release]; _url = [newURL retain]; } - (TRString *) baseDN { return (_baseDN); } - (void) setBaseDN: (TRString *) baseDN { if (_baseDN) [_baseDN release]; _baseDN = [baseDN retain]; } - (TRString *) searchFilter { return (_searchFilter); } - (BOOL) requireGroup { return (_requireGroup); } - (void) setRequireGroup: (BOOL) requireGroup { _requireGroup = requireGroup; } - (void) setSearchFilter: (TRString *) searchFilter { if (_searchFilter) [_searchFilter release]; _searchFilter = [searchFilter retain]; } - (BOOL) referralEnabled { return (_referralEnabled); } - (void) setReferralEnabled: (BOOL) newReferralSetting { _referralEnabled = newReferralSetting; } - (int) timeout { return (_timeout); } - (void) setTimeout: (int) newTimeout { _timeout = newTimeout; } - (TRString *) tlsCACertFile { return (_tlsCACertFile); } - (void) setTLSCACertFile: (TRString *) fileName { if (_tlsCACertFile) [_tlsCACertFile release]; _tlsCACertFile = [fileName retain]; } - (TRString *) tlsCACertDir { return (_tlsCACertDir); } - (void) setTLSCACertDir: (TRString *) directoryName { if (_tlsCACertDir) [_tlsCACertDir release]; _tlsCACertDir = [directoryName retain]; } - (TRString *) tlsCertFile { return (_tlsCertFile); } - (void) setTLSCertFile: (TRString *) fileName { if (_tlsCertFile) [_tlsCertFile release]; _tlsCertFile = [fileName retain]; } - (TRString *) tlsKeyFile { return (_tlsKeyFile); } - (void) setTLSKeyFile: (TRString *) fileName { if (_tlsKeyFile) [_tlsKeyFile release]; _tlsKeyFile = [fileName retain]; } - (TRString *) tlsCipherSuite { return (_tlsCipherSuite); } - (void) setTLSCipherSuite: (TRString *) cipherSuite { if (_tlsCipherSuite) [_tlsCipherSuite release]; _tlsCipherSuite = [cipherSuite retain]; } - (void) setPFTable: (TRString *) tableName { if (_pfTable) [_pfTable release]; _pfTable = [tableName retain]; } - (TRString *) pfTable { return (_pfTable); } - (BOOL) pfEnabled { return (_pfEnabled); } - (void) setPFEnabled: (BOOL) newPFSetting { _pfEnabled = newPFSetting; } - (TRArray *) ldapGroups { return _ldapGroups; } - (BOOL) passWordIsCR { return (_passwordISCR); } - (void) setPassWordIsCR: (BOOL) newCRSetting { _passwordISCR = newCRSetting; } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRAutoreleasePool.h000066400000000000000000000024311332642612100232450ustar00rootroot00000000000000/* * TRAutoreleasePool.h vi:ts=4:sw=4:expandtab: * * Copyright (C) 2006 - 2007 Landon Fuller * All rights reserved. * * Author: Landon Fuller * * This file is part of Substrate. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. * * We disclaim all warranties with regard to this software, including all * implied warranties of merchantability and fitness, in no event shall * we be liable for any special, indirect or consequential damages or any * damages whatsoever resulting from loss of use, data or profits, whether in * an action of contract, negligence or other tortious action, arising out of * or in connection with the use or performance of this software. */ #ifdef HAVE_CONFIG_H #import #endif #import "TRObject.h" typedef struct _TRAutoreleasePoolBucket TRAutoreleasePoolBucket; @interface TRAutoreleasePool : TRObject { @private TRAutoreleasePoolBucket *poolBucket; } + (void) addObject:(id)anObject; - (void) addObject:(id)anObject; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRAutoreleasePool.m000066400000000000000000000137441332642612100232630ustar00rootroot00000000000000/* * TRAutoreleasePool.m vi:ts=4:sw=4:expandtab: * * Copyright (C) 2006 - 2007 Landon Fuller * All rights reserved. * * Author: Landon Fuller #endif #import #import #import #import "xmalloc.h" #import "TRAutoreleasePool.h" /* Number of objects to store in each pool bucket. * Selected arbitrarily. */ #define BUCKET_SIZE 1024 /* * Each thread maintains a stack * of TRAutoreleasePools. */ typedef struct _TRAutoreleasePoolStack { TRAutoreleasePool *pool; struct _TRAutoreleasePoolStack *next; } TRAutoreleasePoolStack; /* * TRAutoreleasePools store autoreleased * objects in a linked list of buckets. */ struct _TRAutoreleasePoolBucket { int count; id objects[BUCKET_SIZE]; struct _TRAutoreleasePoolBucket *next; }; #ifdef HAVE_THREADLS static __thread TRAutoreleasePoolStack *autorelease_stack; # define CURTHREAD_GET_POOLSTACK() autorelease_stack # define CURTHREAD_SET_POOLSTACK(x) autorelease_stack = x #else static pthread_key_t autorelease_stack_key; # define CURTHREAD_GET_POOLSTACK() (TRAutoreleasePoolStack *) pthread_getspecific(autorelease_stack_key) # define CURTHREAD_SET_POOLSTACK(x) pthread_setspecific(autorelease_stack_key, (void *) x) #endif /* HAVE_THEADLS */ /* * Allocate and initialize a new bucket, attach it to the * supplied bucket. */ static TRAutoreleasePoolBucket *bucket_add (TRAutoreleasePoolBucket *bucket) { TRAutoreleasePoolBucket *new; /* Allocate and initialize the bucket */ new = xmalloc(sizeof(TRAutoreleasePoolBucket)); new->count = 0; new->next = bucket; return new; } /* * Free the bucket stack, sending release messages to the contained objects. */ static void bucket_flush (TRAutoreleasePoolBucket *bucket) { TRAutoreleasePoolBucket *next, *cur; int i; /* Free all buckets */ cur = bucket; while (cur != NULL) { /* Send release message to all objects in the bucket */ for (i = 0; i < cur->count; i++) { [cur->objects[i] release]; } next = cur->next; free(cur); cur = next; } } /*! * @brief Foundation Allocation Pool Class. * * TRAutoreleasePool provides an API for implementing per-thread pools of * autoreleased objects. When an object is sent the autorelease method, * it is added to the current thread's autorelease pool. Per-thread * pools are implemented using a stack -- when a new pool is allocated, * it is pushed onto the stack, and all new autoreleased objects are * placed in that pool. * * When the autorelease pool is deallocated, all autoreleased objects * are sent release messages. You may add an object to an autorelease * pool multiple times, and it will be sent multiple release messages. * * You must deallocate autorelease pools in the same order they were * allocated. */ @implementation TRAutoreleasePool #ifndef HAVE_THREADLS + (void) initialize { if (self != [TRAutoreleasePool class]) return; /* Initialize our pthread key */ pthread_key_create(&autorelease_stack_key, NULL); } #endif - (id) init { TRAutoreleasePoolStack *stack, *threadStack; if ((self = [super init]) == nil) { return self; } /* Grab the thread-specific pool stack pointer */ threadStack = CURTHREAD_GET_POOLSTACK(); /* Allocate our new stack */ stack = xmalloc(sizeof(TRAutoreleasePoolStack)); stack->pool = self; /* If a current stack exists, append the new one, * otherwise, we're the first stack */ if (threadStack != NULL) /* We are a sub-pool */ stack->next = threadStack; else /* We are the first pool */ stack->next = NULL; /* Set new per-thread pool stack */ CURTHREAD_SET_POOLSTACK(stack); /* Allocate and initialize our bucket */ poolBucket = xmalloc(sizeof(TRAutoreleasePoolBucket)); poolBucket->count = 0; poolBucket->next = NULL; return self; } - (void) dealloc { TRAutoreleasePoolStack *stack; /* Free our buckets */ bucket_flush(poolBucket); /* Pop our pool stack */ stack = CURTHREAD_GET_POOLSTACK(); CURTHREAD_SET_POOLSTACK(stack->next); free(stack); [super dealloc]; } /*! * Add anObject to the current thread's * active autorelease pool. */ + (void) addObject:(id)anObject { TRAutoreleasePoolStack *stack; /* Get our per-thread stack */ stack = CURTHREAD_GET_POOLSTACK(); assert(stack != NULL); [stack->pool addObject: anObject]; } /*! * Add anObject to the receiver. */ - (void) addObject:(id)anObject { /* If the current bucket is full, create a new one */ if (poolBucket->count == BUCKET_SIZE) { poolBucket = bucket_add(poolBucket); } poolBucket->objects[poolBucket->count] = anObject; poolBucket->count++; } - (id) retain { /* Can not retain an autorelease pool. */ abort(); /* Not reached. */ return nil; } - (id) autorelease { /* Can not autorelease an autorelease pool. */ abort(); /* Not reached */ return nil; } @end /*! @} */ openvpn-auth-ldap-auth-ldap-2.0.4/src/TRConfig.h000066400000000000000000000044721332642612100213560ustar00rootroot00000000000000/* * TRConfig.h vi:ts=4:sw=4:expandtab: * Generic Configuration Parser * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRObject.h" #import "TRConfigToken.h" @protocol TRConfigDelegate - (void) setKey: (TRConfigToken *) name value: (TRConfigToken *) value; - (void) startSection: (TRConfigToken *) sectionType sectionName: (TRConfigToken *) name; - (void) endSection: (TRConfigToken *) sectionEnd; - (void) parseError: (TRConfigToken *) badToken; @end @interface TRConfig : TRObject { @private int _fd; BOOL _error; id _delegate; } - (id) initWithFD: (int) fd configDelegate: (id ) delegate; - (BOOL) parseConfig; /* Callback used to stop the running parser */ - (void) errorStop; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRConfig.m000066400000000000000000000070331332642612100213570ustar00rootroot00000000000000/* * TRConfig.m vi:ts=4:sw=4:expandtab: * Generic Configuration Parser * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import #import "TRConfig.h" #import "TRConfigLexer.h" #import "TRConfigParser.h" #import "TRConfigToken.h" /** * An Apache-style configuration file parser/lexer. */ @implementation TRConfig /** * Initialize and return a TRConfig parser. * @param fd A file descriptor open for reading. This file descriptor will be * mmap()ed, and thus must reference a file. * @param delegate A configuration delegate conforming to the TRConfigDelegate protocol. */ - (id) initWithFD: (int) fd configDelegate: (id ) delegate { self = [self init]; if (self) { _fd = fd; _delegate = delegate; _error = NO; } return self; } /** * Parse the configuration file * @result true on success, false on failure. */ - (BOOL) parseConfig { TRConfigLexer *lexer = NULL; TRConfigToken *token; void *parser; /* Initialize our lexer */ lexer = [[TRConfigLexer alloc] initWithFD: _fd]; if (lexer == NULL) return false; /* Initialize the parser */ parser = TRConfigParseAlloc(malloc); /* Scan in tokens and hand them off to the parser */ while ((token = [lexer scan]) != NULL) { TRConfigParse(parser, [token tokenID], token, _delegate); /* If we've been asked to stop, do so */ if (_error) break; } /* Signal EOF and clean up */ if (!_error) { /* Only trigger EOF handling if no errors occured */ TRConfigParse(parser, 0, NULL, _delegate); } TRConfigParseFree(parser, free); [lexer release]; /* Did an error occur? */ if (_error) return false; return true; } /* Re-entrant callback used to signal an error by the parser delegate, called * from within the bowels of TRConfigParse() */ - (void) errorStop { _error = YES; } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRConfigLexer.h000066400000000000000000000044251332642612100223540ustar00rootroot00000000000000/* * TRConfigLexer.h vi:ts=4:sw=4:expandtab: * Configuration Lexer * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import "TRObject.h" #import "TRConfigToken.h" typedef enum { LEXER_SC_INITIAL, LEXER_SC_SECTION, LEXER_SC_SECTION_NAME, LEXER_SC_VALUE, LEXER_SC_STRING_VALUE } LexerStartCondition; @interface TRConfigLexer : TRObject { @private /* Input buffer */ char *buffer; size_t bufferLength; /* re2c lexer state */ char *_cursor; char *_limit; char *_marker; char *_ctxMarker; char *_token; char *_eoi; unsigned int _lineNumber; LexerStartCondition _condition; } - (id) initWithFD: (int) fd; - (TRConfigToken *) scan; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRConfigLexer.re000066400000000000000000000231541332642612100225330ustar00rootroot00000000000000/* * TRConfigLexer.re vi:ts=4:sw=4:expandtab: * Configuration Lexer * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import #import #import #import #import #import "TRConfig.h" #import "TRConfigLexer.h" #import "TRConfigParser.h" /* * re2c Configuration */ #define YYCTYPE char /* Input Symbol Type */ #define YYCURSOR _cursor /* L-expression of type *YYCTYPE that points to the current input symbol */ #define YYLIMIT _limit /* Expression of type *YYCTYPE that marks the end of the buffer */ #define YYMARKER _marker /* L-expression of type *YYCTYPE that is used for backtracking information */ #define YYCTXMARKER _ctxMarker /* L-expression of type *YYCTYPE that is used for trailing context back tracking information */ #define YYFILL(n) [self fill: n] /* YYFILL(n) is called when the buffer needs (re)filling */ #define YYDEBUG(state, current) printf("state: %d, current: '%c' (%d)\n", state, current, current); /* * Macros */ /* Increment line count */ #define INCR_LINE() _lineNumber++ /* Switch to a start condition */ #define BEGIN(cond) ( _condition = LEXER_SC_ ## cond) /* Declare a start condition */ #define SC(cond) LEXER_SC_ ## cond: LEXER_SC_ ## cond /* Check for end-of-input */ #define CHECK_EOI() if (_eoi) { return NULL; } /* Skip a token */ #define SKIP(cond) CHECK_EOI(); goto LEXER_SC_ ## cond /* Get the current token length */ #define TOKEN_LENGTH() (_cursor - _token) @implementation TRConfigLexer - (void) dealloc { if (buffer) munmap(buffer, bufferLength); [super dealloc]; } - (id) initWithFD: (int) fd { struct stat statbuf; /* Initialize */ self = [self init]; if (self == NULL) return (self); /* Mmap() source file * Unless our caller botched something, this should never fail */ assert((fstat(fd, &statbuf) == 0)); bufferLength = statbuf.st_size; buffer = mmap(NULL, bufferLength, PROT_READ, MAP_SHARED, fd, 0); assert(buffer != MAP_FAILED); /* Initialize lexer state */ _lineNumber = 1; _condition = LEXER_SC_INITIAL; _cursor = buffer; _limit = _cursor + bufferLength - 1; return (self); } - (void) fill: (int) length { /* We just need to prevent re2c from walking off the end of our buffer */ assert(_limit - _cursor >= 0); if (_cursor == _limit) { /* Save the cursor and signal EOI */ _eoi = _cursor; } } - (TRConfigToken *) scan { TRConfigToken *token; /*!re2c /* vim syntax fix */ any = .; key = [A-Za-z0-9_-]+; */ /* Test for EOI before scanning */ CHECK_EOI(); switch (_condition) { case SC(INITIAL): _token = _cursor; /*!re2c /* vim syntax fix */ /* Skip white space */ [ \t]+ { SKIP(INITIAL); } /* Skip comments */ "#".* { SKIP(INITIAL); } /* Keys */ key { token = [[TRConfigToken alloc] initWithBytes: _token numBytes: TOKEN_LENGTH() lineNumber: _lineNumber tokenID: TOKEN_KEY]; BEGIN(VALUE); return token; } /* Sections */ "<" { SKIP(SECTION); } /* Skip blank lines */ "\n" { INCR_LINE(); SKIP(INITIAL); } /* Handle unknown characters */ any { // TODO explode here printf("Unknown character: '%c' (%d)\n", yych, yych); return NULL; } */ break; /* Section Declarations */ case SC(SECTION): _token = _cursor; /*!re2c /* vim syntax fix */ /* Unnamed section */ key">" { /* Drop the trailing ">" */ token = [[TRConfigToken alloc] initWithBytes: _token numBytes: TOKEN_LENGTH() - 1 lineNumber: _lineNumber tokenID: TOKEN_SECTION_START]; return token; } /* Named section */ key/[ \t]+ { token = [[TRConfigToken alloc] initWithBytes: _token numBytes: TOKEN_LENGTH() lineNumber: _lineNumber tokenID: TOKEN_SECTION_START]; BEGIN(SECTION_NAME); return token; } /* Section end */ "/"key">" { /* Drop the leading '/' and trailing ">" */ token = [[TRConfigToken alloc] initWithBytes: _token + 1 numBytes: TOKEN_LENGTH() - 2 lineNumber: _lineNumber tokenID: TOKEN_SECTION_END]; return token; } /* End of line returns to the initial state */ "\n" { INCR_LINE(); SKIP(INITIAL); } */ break; case SC(SECTION_NAME): _token = _cursor; /*!re2c /* vim syntax fix */ /* Skip white space */ [ \t]+ { SKIP(SECTION_NAME); } /* Section name */ key">" { /* Drop the trailing ">" */ token = [[TRConfigToken alloc] initWithBytes: _token numBytes: TOKEN_LENGTH() - 1 lineNumber: _lineNumber tokenID: TOKEN_SECTION_NAME]; BEGIN(INITIAL); return token; } /* End of line returns to the initial state */ "\n" { INCR_LINE(); SKIP(INITIAL); } */ /* Values */ case SC(VALUE): _token = _cursor; /*!re2c /* vim syntax fix */ [ \t]+ { SKIP(VALUE); } /* Skip trailing comments */ "#".* { SKIP(VALUE); } /* Value is a quoted string */ "\"" { SKIP(STRING_VALUE); } /* Single word value, skip leading whitespace */ [^ \t\n"]+ { /* " vim syntax fix */ token = [[TRConfigToken alloc] initWithBytes: _token numBytes: TOKEN_LENGTH() lineNumber: _lineNumber tokenID: TOKEN_VALUE]; return token; } /* End of line returns to the initial state */ "\n" { INCR_LINE(); SKIP(INITIAL); } */ break; /* Quoted string values */ case SC(STRING_VALUE): _token = _cursor; /*!re2c /* vim syntax fix */ /* Skip trailing comments */ "#".* { SKIP(STRING_VALUE); } /* Quoted strings */ /* "\""[^\"]+"\"" { */ [^"]+"\"" { /* Skip the trailing '"' */ token = [[TRConfigToken alloc] initWithBytes: _token numBytes: TOKEN_LENGTH() - 1 lineNumber: _lineNumber tokenID: TOKEN_VALUE]; return token; } /* End of line returns to the initial state */ "\n" { INCR_LINE(); SKIP(INITIAL); } */ break; default: /* Impossible */ assert(0); } /* Never reached */ return nil; } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRConfigParser.lemon000066400000000000000000000053661332642612100234210ustar00rootroot00000000000000/* * TRConfigParser.lemon vi:ts=4:sw=4:expandtab: * Configuration Parser * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ %include { #ifdef HAVE_CONFIG_H #import #endif #import "TRConfig.h" #import } %name TRConfigParse %token_type {TRConfigToken *} %token_prefix {TOKEN_} %extra_argument {id configDelegate} %token_destructor { [$$ release]; /* quiesces unused variable compiler warning */ if (NO) [configDelegate class]; } %syntax_error { [configDelegate parseError: TOKEN]; } config_file ::= lines. lines ::= . lines ::= lines declaration. lines ::= lines section. declaration ::= KEY(key) VALUE(keyValue). { [configDelegate setKey: key value: keyValue]; [key release]; [keyValue release]; } section ::= declare_section lines SECTION_END(end). { [configDelegate endSection: end]; [end release]; } declare_section ::= SECTION_START(type) SECTION_NAME(name). { [configDelegate startSection: type sectionName: name]; [type release]; [name release]; } declare_section ::= SECTION_START(type). { [configDelegate startSection: type sectionName: nil]; [type release]; } openvpn-auth-ldap-auth-ldap-2.0.4/src/TRConfigToken.h000066400000000000000000000055601332642612100223560ustar00rootroot00000000000000/* * TRConfigToken.h vi:ts=4:sw=4:expandtab: * Configuration Lexer Tokens * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import #import "TRObject.h" #import "TRString.h" /** * Object Data Types. * Tokens are always strings (TOKEN_DATATYPE_STRING), * but sometimes they can also be integers and booleans. * In other words, the integer and boolean datatypes should * be considered to provide a superset of functionality to the * string data type. */ typedef enum { TOKEN_DATATYPE_STRING, TOKEN_DATATYPE_INT, TOKEN_DATATYPE_BOOL } TRConfigDataType; @interface TRConfigToken : TRObject { @private /* Parser's token identifier */ int _tokenID; /* Token's line origin */ unsigned int _lineNumber; /* String value */ TRString *_string; /* Current data type */ TRConfigDataType _dataType; /* Union of internal representations */ union { int _intValue; BOOL _boolValue; } _internalRep; } - (id) initWithBytes: (const char *) data numBytes: (size_t) length lineNumber: (unsigned int) line tokenID: (int) tokenID; - (int) tokenID; - (unsigned int) lineNumber; - (TRString *) string; - (const char *) cString; - (BOOL) intValue: (int *) value; - (BOOL) boolValue: (BOOL *) value; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRConfigToken.m000066400000000000000000000123001332642612100223510ustar00rootroot00000000000000/* * TRConfigToken.m vi:ts=4:sw=4:expandtab: * Configuration Lexer Tokens * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import #import "TRConfigToken.h" /** * Represents a config file parser token. */ @implementation TRConfigToken - (void) dealloc { if (_string) [_string release]; [super dealloc]; } - (id) initWithBytes: (const char *) data numBytes: (size_t) length lineNumber: (unsigned int) line tokenID: (int) tokenID { self = [self init]; if (self != NULL) { _dataType = TOKEN_DATATYPE_STRING; _tokenID = tokenID; _lineNumber = line; _string = [[TRString alloc] initWithBytes: data numBytes: length]; if (!_string) { [self release]; return NULL; } } return (self); } /** * Return the lemon token id. */ - (int) tokenID { return _tokenID; } /** * Return the line number from which the token was parsed. */ - (unsigned int) lineNumber { return _lineNumber; } /** * Return the token's string value. */ - (TRString *) string { return _string; } /** * Return the token's C string value. * @return NULL terminated C string. The result is only valid for the * lifetime of the TRConfigToken object. */ - (const char *) cString { return [_string cString]; } /** * Get the token's integer value. * Returns true on success, false on failure. * The integer value will be stored in the value argument. * * If the token is not a valid integer, value will be set to 0 * and the method will return false. * If the token is larger than INT_MAX, value will be set to INT_MAX * and the method will return false. If the token is smaller than INT_MIN, * value will be set to INT_MIN and the method will also return false. * * @param value Pointer where the integer value will be stored * @result true on success, false on failure. */ - (BOOL) intValue: (int *) value { BOOL result; /* Check if the integer conversion has been cached */ if (_dataType == TOKEN_DATATYPE_INT) { *value = _internalRep._intValue; return true; } /* Otherwise, do the conversion and return the result, * caching on success */ result = [_string intValue: value]; if (result) { _dataType = TOKEN_DATATYPE_INT; _internalRep._intValue = *value; } return result; } /** * Get the token's boolean value. * Returns true on success, false on failure. * The boolean value will be stored in the value argument. * * If the token is not a valid boolean ("yes", "no", "true", "false", "1", or "0", * value will be set to false and the method will return false. * * @param value Pointer where the boolean value will be stored * @result true on success, false on failure. */ - (BOOL) boolValue: (BOOL *) value { const char *cString; /* Check if the integer conversion has been cached */ if (_dataType == TOKEN_DATATYPE_BOOL) { *value = _internalRep._boolValue; return (YES); } /* Otherwise, do the conversion and return the result, * caching on success */ cString = [_string cString]; if (strcasecmp(cString, "yes") == 0 || strcasecmp(cString, "true") == 0 || strcasecmp(cString, "1") == 0) { _dataType = TOKEN_DATATYPE_BOOL; _internalRep._boolValue = YES; *value = YES; return (YES); } else if (strcasecmp(cString, "no") == 0 || strcasecmp(cString, "false") == 0 || strcasecmp(cString, "0") == 0) { _dataType = TOKEN_DATATYPE_BOOL; _internalRep._boolValue = NO; *value = NO; return (YES); } *value = NO; return (NO); } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TREnumerator.h000066400000000000000000000035271332642612100222720ustar00rootroot00000000000000/* * TREnumerator.h vi:ts=4:sw=4:expandtab: * Abstract enumerator class * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRObject.h" @protocol TREnumerator - (id) nextObject; @end @interface TREnumerator : TRObject - (id) nextObject; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TREnumerator.m000066400000000000000000000035131332642612100222720ustar00rootroot00000000000000/* * TREnumerator.m vi:ts=4:sw=4:expandtab: * Abstract enumerator class * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TREnumerator.h" /** * Abstract enumerator superclass. */ @implementation TREnumerator - (id) nextObject { return nil; } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRHash.h000066400000000000000000000040701332642612100210260ustar00rootroot00000000000000/* * TRHash.h vi:ts=4:sw=4:expandtab: * Hash table * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "hash.h" #import "TRObject.h" #import "TRString.h" #import "TREnumerator.h" @interface TRHash : TRObject { @private hash_t *_hash; } - (id) initWithCapacity: (unsigned long) numItems; - (BOOL) isFull; - (id) valueForKey: (TRString *) key; - (void) setObject: (id) anObject forKey: (TRString *) key; - (void) removeObjectForKey: (TRString *) key; - (TREnumerator *) keyEnumerator; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRHash.m000066400000000000000000000132731332642612100210400ustar00rootroot00000000000000/* * TRHash.m vi:ts=4:sw=4:expandtab: * Hash Table * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import #import "TRHash.h" /** * Hash key enumerator. */ @interface TRHashKeyEnumerator : TREnumerator { TRHash *_hash; hscan_t _scan; hash_t *_hashContext; } - (id) initWithHash: (TRHash *) hash; @end /* * Private Methods */ @interface TRHash (Private) - (hash_t *) _privateHashContext; @end /** * A hash table implementation. */ @implementation TRHash /* * Supporting functions */ static hash_val_t hash_function(const void *key) { return [(TRString *) key hash]; } static int hash_key_compare(const void *firstValue, const void *secondValue) { return strcmp([(TRString *) firstValue cString], [(TRString *) secondValue cString]); } - (void) dealloc { hscan_t scan; hnode_t *node; /* Release every member of the hash */ hash_scan_begin(&scan, _hash); while ((node = hash_scan_next(&scan)) != NULL) { /* Remove the node from the hash table */ hash_scan_delete(_hash, node); /* Release the data */ id obj; obj = (id) hnode_get(node); [obj release]; /* Release the key */ obj = (id) hnode_getkey(node); [obj release]; /* Destroy the node */ hnode_destroy(node); } /* Deallocate the hash table */ hash_destroy(_hash); /* Pass control on to our superclass */ [super dealloc]; } /** * Initialize a new TRHash with an maximum capacity of * numItems. */ - (id) initWithCapacity: (unsigned long) numItems { self = [self init]; if (!self) return nil; /* Initialize our hash table */ _hash = hash_create(numItems, &hash_key_compare, &hash_function); return self; } /** * If the hash is full, returns YES. * Attempting to add an item to a full hash will trigger an assertion. */ - (BOOL) isFull { if (hash_isfull(_hash)) return YES; else return NO; } /** * Remove the key and associated value from the hash table. */ - (void) removeObjectForKey: (TRString *) key { hnode_t *node; id obj; /* Look for an existing key */ node = hash_lookup(_hash, key); if (!node) return; /* Remove the node */ tr_hash_delete(_hash, node); /* Drop the old value */ obj = (id) hnode_get(node); [obj release]; /* Drop the old key */ obj = (id) hnode_getkey(node); [obj release]; /* Destroy the node */ hnode_destroy(node); } /** * Returns the associated value for a given key. */ - (id) valueForKey: (TRString *) key { hnode_t *node; /* Look up the key */ node = hash_lookup(_hash, key); if (!node) return nil; /* Return associated value */ return (id) hnode_get(node); } /** * Add anObject to the hash table with key. * Both the key and value are retained. */ - (void) setObject: (id) anObject forKey: (TRString *) key { hnode_t *node; /* Remove the key, if it exists */ [self removeObjectForKey: key]; /* Are we at capacity? Programmer error! */ assert(hash_isfull(_hash) == 0); /* Retain our key and value */ [anObject retain]; [key retain]; /* Insert them into the hash table */ node = hnode_create(anObject); hash_insert(_hash, node, key); } - (hash_t *) _privateHashContext { return _hash; } /** * Return a key enumerator. * Due to our lack of an autorelease pool, * it is the caller's responsibility to release * the returned value. */ - (TREnumerator *) keyEnumerator { return [[[TRHashKeyEnumerator alloc] initWithHash: self] autorelease]; } @end /* TRHash */ @implementation TRHashKeyEnumerator - (void) dealloc { [_hash release]; [super dealloc]; } - (id) initWithHash: (TRHash *) hash { self = [super init]; if (!self) return self; _hash = [hash retain]; _hashContext = [hash _privateHashContext]; hash_scan_begin(&_scan, _hashContext); return self; } - (id) nextObject { hnode_t *node; node = hash_scan_next(&_scan); if (!node) return nil; return (id) hnode_getkey(node); } @end /* TRHashKeyEnumerator */ openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPAccountRepository.h000066400000000000000000000046251332642612100243060ustar00rootroot00000000000000/* * TRLDAPAccountRepository.h vi:ts=4:sw=4:expandtab: * * Author: Landon Fuller * * Copyright (c) 2008-2012 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRObject.h" #import "TRString.h" #import "TRAccountRepository.h" #import "TRLDAPConnection.h" #import "TRLDAPSearchFilter.h" /** * LDAP user/group account verification. */ @interface TRLDAPAccountRepository : TRObject { @private TRLDAPConnection *_ldap; TRLDAPSearchFilter *_userFilter; TRLDAPSearchFilter *_groupFilter; } - (id) initWithLDAPConnection: (TRLDAPConnection *) ldap userSearchFilter: (TRLDAPSearchFilter *) userFilter groupSearchFilter: (TRLDAPSearchFilter *) groupFilter; - (BOOL) authenticateUser: (TRString *) username withPassword: (TRString *) password; - (BOOL) checkGroupMember: (TRString *) username withGroup: (TRString *) groupname; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPAccountRepository.m000066400000000000000000000057211332642612100243110ustar00rootroot00000000000000/* * TRLDAPAccountRepository.m vi:ts=4:sw=4:expandtab: * * Author: Landon Fuller * * Copyright (c) 2008 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRLDAPAccountRepository.h" @implementation TRLDAPAccountRepository /** * Initialize a new TRLDAPAccountRepository instance with the provided * TRLDAPConnection. */ - (id) initWithLDAPConnection: (TRLDAPConnection *) ldap userSearchFilter: (TRLDAPSearchFilter *) userFilter groupSearchFilter: (TRLDAPSearchFilter *) groupFilter { /* Initialize our superclass */ self = [super init]; if (self == nil) return nil; /* Save a reference to the LDAP connection */ _ldap = [ldap retain]; _userFilter = [userFilter retain]; _groupFilter = [groupFilter retain]; return self; } - (void) dealloc { /* Release our LDAP connection. */ [_ldap release]; /* User filter. */ [_userFilter release]; /* Group filter. */ [_groupFilter release]; /* Deallocate the superclass */ [super dealloc]; } /** * Authenticate a user with the provided username and password. * From TRAccountRepository protocol. */ - (BOOL) authenticateUser: (TRString *) username withPassword: (TRString *) password { return NO; } /** * Check if the given username is a member of a group. * From TRAccountRepository protocol. */ - (BOOL) checkGroupMember: (TRString *) username withGroup: (TRString *) groupname { return NO; } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPConnection.h000066400000000000000000000052041332642612100227030ustar00rootroot00000000000000/* * TRLDAPConnection.h vi:ts=4:sw=4:expandtab: * Simple LDAP Wrapper * * Copyright (c) 2005 - 2007 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import "TRObject.h" #import "TRLDAPEntry.h" #import "TRString.h" #import "TRArray.h" @interface TRLDAPConnection : TRObject { @private LDAP *ldapConn; int _timeout; } - (id) initWithURL: (TRString *) url timeout: (int) timeout; - (BOOL) startTLS; - (BOOL) bindWithDN: (TRString *) bindDN password: (TRString *) password; - (TRArray *) searchWithFilter: (TRString *) filter scope: (int) scope baseDN: (TRString *) base attributes: (TRArray *) attributes; - (BOOL) compare: (TRString *) dn withAttribute: (TRString *) attribute value: (TRString *) value; - (BOOL) compareDN: (TRString *) dn withAttribute: (TRString *) attribute value: (TRString *) value; - (BOOL) setReferralEnabled: (BOOL) enabled; - (BOOL) setTLSCACertFile: (TRString *) fileName; - (BOOL) setTLSCACertDir: (TRString *) directory; - (BOOL) setTLSClientCert: (TRString *) certFile keyFile: (TRString *) keyFile; - (BOOL) setTLSCipherSuite: (TRString *) cipherSuite; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPConnection.m000066400000000000000000000404211332642612100227100ustar00rootroot00000000000000/* * TRLDAPConnection.m vi:ts=4:sw=4:expandtab: * Simple LDAP Wrapper * * Copyright (c) 2005 - 2007 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import #import #import "TRLDAPConnection.h" #import "TRLog.h" #import "xmalloc.h" /* Maximum number of unique attributes returned for a given entry. */ #define MAX_ATTRIBUTES 2048 static int ldap_get_errno(LDAP *ld) { int err; if (ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err) != LDAP_OPT_SUCCESS) err = LDAP_OTHER; return err; } /* * Private Methods */ @interface TRLDAPConnection (Private) - (void) log: (loglevel_t) level withLDAPError: (int) error message: (char *) message; - (BOOL) setLDAPOption: (int) opt value: (const char *) value connection: (LDAP *) ldapConn; - (BOOL) setTLSRequireCert; @end @implementation TRLDAPConnection (Private) /** * Log an LDAP error, including the LDAP_OPT_ERROR_STRING, if available. */ - (void) log: (loglevel_t) level withLDAPError: (int) error message: (char *) message { char *ld_error = NULL; ldap_get_option(ldapConn, LDAP_OPT_ERROR_STRING, &ld_error); if (ld_error && strlen(ld_error) != 0) { [TRLog log: level withMessage: "%s: %s (%s)", message, ldap_err2string(error), ld_error]; } else { [TRLog log: level withMessage: "%s: %s", message, ldap_err2string(error)]; } if (ld_error) { ldap_memfree(ld_error); } } /** * Set an LDAP option. */ - (BOOL) setLDAPOption: (int) opt value: (const char *) value connection: (LDAP *) ldapConn { int err; if ((err = ldap_set_option(NULL, opt, (const void *) value)) != LDAP_SUCCESS) { [TRLog debug: "Unable to set ldap option %d to %s: %d: %s", opt, value == NULL ? "False" : value, err, ldap_err2string(err)]; return (false); } return true; } /** * Always require a valid certificate */ - (BOOL) setTLSRequireCert { int err; int arg; arg = LDAP_OPT_X_TLS_HARD; if ((err = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &arg)) != LDAP_SUCCESS) { [TRLog debug: "Unable to set LDAP_OPT_X_TLS_HARD to %d: %d: %s", arg, err, ldap_err2string(err)]; return (false); } return (true); } @end /* * Public Methods */ @implementation TRLDAPConnection - (id) initWithURL: (TRString *) url timeout: (int) timeout { struct timeval ldapTimeout; int arg; self = [self init]; if (!self) return NULL; ldap_initialize(&ldapConn, [url cString]); if (!ldapConn) { [TRLog error: "Unable to initialize LDAP server %s", [url cString]]; [self release]; return (NULL); } _timeout = timeout; ldapTimeout.tv_sec = _timeout; ldapTimeout.tv_usec = 0; if (ldap_set_option(ldapConn, LDAP_OPT_NETWORK_TIMEOUT, &ldapTimeout) != LDAP_OPT_SUCCESS) [TRLog warning: "Unable to set LDAP network timeout."]; arg = LDAP_VERSION3; if (ldap_set_option(ldapConn, LDAP_OPT_PROTOCOL_VERSION, &arg) != LDAP_OPT_SUCCESS) { [TRLog error: "Unable to enable LDAP v3 Protocol."]; [self release]; return (NULL); } return (self); } - (void) dealloc { int err; err = ldap_unbind_ext_s(ldapConn, NULL, NULL); if (err != LDAP_SUCCESS) { [self log: TRLOG_WARNING withLDAPError: err message: "Unable to unbind from LDAP server"]; } [super dealloc]; } /** * Start TLS on the LDAP connection. */ - (BOOL) startTLS { int err; err = ldap_start_tls_s(ldapConn, NULL, NULL); if (err != LDAP_SUCCESS) { [self log: TRLOG_ERR withLDAPError: err message: "Unable to enable STARTTLS"]; return (NO); } return (YES); } - (BOOL) bindWithDN: (TRString *) bindDN password: (TRString *) password { int msgid, err; LDAPMessage *res; struct berval cred; struct berval *servercred = NULL; struct timeval timeout; /* Set up berval structure for our credentials */ cred.bv_val = (char *) [password cString]; cred.bv_len = [password length] - 1; /* Length includes NULL terminator */ /* * By default, some LDAP servers, in accordance with the RFC, treat a bind * with a valid DN and an empty (zero length) password as a successful * anonymous bind. There is no way to determine from the bind result * whether the bind was anonymous. Thus, we must forbid zero length * passwords. */ if (cred.bv_len == 0) { [TRLog error: "ldap_bind with zero-length password is forbidden."]; return (false); } if ((err = ldap_sasl_bind(ldapConn, [bindDN cString], LDAP_SASL_SIMPLE, &cred, NULL, NULL, &msgid)) != LDAP_SUCCESS) { [self log: TRLOG_ERR withLDAPError: err message: "LDAP bind failed immediately"]; return (false); } /* Wait for the result */ timeout.tv_sec = _timeout; timeout.tv_usec = 0; if (ldap_result(ldapConn, msgid, 1, &timeout, &res) <= 0) { err = ldap_get_errno(ldapConn); if (err == LDAP_TIMEOUT) ldap_abandon_ext(ldapConn, msgid, NULL, NULL); [self log: TRLOG_ERR withLDAPError: err message: "LDAP bind failed"]; return (false); } /* Parse the bind result */ err = ldap_parse_sasl_bind_result(ldapConn, res, &servercred, 0); if (servercred != NULL) ber_bvfree(servercred); /* Did the parse (not the bind) succeed. Different LDAP * libraries seem to differ on whether this is the parse result, * or the bind result, so we play it safe and pull the bind result */ if (err != LDAP_SUCCESS) { ldap_msgfree(res); return false; } /* Did the the bind succeed? */ if (ldap_parse_result(ldapConn, res, &err, NULL, NULL, NULL, NULL, 1) != LDAP_SUCCESS) { /* Parsing failed */ return false; } if (err == LDAP_SUCCESS) { /* Bind succeeded */ return (true); } [self log: TRLOG_ERR withLDAPError: err message: "LDAP bind failed"]; return (false); } /** * Run an LDAP search. * @param filter: LDAP search filter. * @param scope: LDAP scope (LDAP_SCOPE_BASE, LDAP_SCOPE_ONE, or LDAP_SCOPE_SUBTREE) * @param base: LDAP search base DN. * @param attributes: Attributes to return. If nil, returns all attributes. * @return: An array of TRLDAPEntry instances. */ - (TRArray *) searchWithFilter: (TRString *) filter scope: (int) scope baseDN: (TRString *) base attributes: (TRArray *) attributes { TREnumerator *iter; LDAPMessage *res; LDAPMessage *entry; char *attr; struct berval **vals; TRArray *entries; struct timeval timeout; char **attrArray; TRString *attrString; int count; int numEntries; int err; count = 0; entries = nil; /* Build the attrArray */ if (attributes) { attrArray = xmalloc(sizeof(char *) * [attributes count]); iter = [attributes objectEnumerator]; while ((attrString = [iter nextObject]) != nil) { attrArray[count] = (char *) [attrString cString]; count++; } } else { /* Return all attributes */ attrArray = NULL; } /* Set up the timeout */ timeout.tv_sec = _timeout; timeout.tv_usec = 0; /* MISSING: * Support for user-specified 'attrOnly' mode. * Non-hardcoded size limit. */ if ((err = ldap_search_ext_s(ldapConn, [base cString], scope, [filter cString], attrArray, 0, NULL, NULL, &timeout, 1024, &res)) != LDAP_SUCCESS) { [self log: TRLOG_ERR withLDAPError: err message: "LDAP search failed"]; goto finish; } /* Get the number of returned entries */ if ((numEntries = ldap_count_entries(ldapConn, res)) == -1) { [TRLog debug: "ldap_count_entries failed: %d: %s", numEntries, ldap_err2string(numEntries)]; goto finish; } /* If 0, return nil */ if (numEntries == 0) { ldap_msgfree(res); goto finish; } /* Allocate an array to hold entries */ entries = [[TRArray alloc] init]; /* Grab attributes and values for each entry */ for (entry = ldap_first_entry(ldapConn, res); entry != NULL; entry = ldap_next_entry(ldapConn, entry)) { TRLDAPEntry *ldapEntry; TRHash *ldapAttributes; BerElement *ptr; int maxCapacity = MAX_ATTRIBUTES; TRString *dn; char *dnCString; ldapAttributes = [[TRHash alloc] initWithCapacity: maxCapacity]; /* Grab our entry's DN */ dnCString = ldap_get_dn(ldapConn, entry); dn = [[TRString alloc] initWithCString: dnCString]; ldap_memfree(dnCString); /* Load all attributes and associated values */ for (attr = ldap_first_attribute(ldapConn, entry, &ptr); attr != NULL; attr = ldap_next_attribute(ldapConn, entry, ptr)) { TRString *attrName; TRString *valueString; TRArray *attrValues; int i; /* Don't exceed the maximum capacity of the hash table */ if(--maxCapacity == 0) { [TRLog error: "Over %d LDAP attributes returned for a single entry. Ignoring any remaining attributes.", MAX_ATTRIBUTES]; break; } attrName = [[TRString alloc] initWithCString: attr]; attrValues = [[TRArray alloc] init]; vals = ldap_get_values_len(ldapConn, entry, attr); if (vals) { for (i = 0; vals[i] != NULL; i++) { /* XXX: This could be binary. This is not the end of the world, but a braindead * client of this API could do something dumb. There doesn't seem to be any sane * way to determine whether data is binary or non-binary. At the very least, we * enforce NULL termination by turning the data into a string. */ valueString = [[TRString alloc] initWithBytes: vals[i]->bv_val numBytes: vals[i]->bv_len]; /* Pass our value string to the attrValues array */ [attrValues addObject: valueString]; [valueString release]; } ldap_value_free_len(vals); } /* Pass our attribute string and array of values to the * entryAttributes hash table */ [ldapAttributes setObject: attrValues forKey: attrName]; [attrName release]; [attrValues release]; ldap_memfree(attr); } /* Free ber ptr */ ber_free(ptr, 0); /* Instantiate our entry */ ldapEntry = [[TRLDAPEntry alloc] initWithDN: dn attributes: ldapAttributes]; [dn release]; [ldapAttributes release]; /* Pass our entry off to the entries array */ [entries addObject: ldapEntry]; [ldapEntry release]; } /* free memory allocated for search results */ ldap_msgfree(res); finish: if (attrArray) free(attrArray); return [entries autorelease]; } - (BOOL) compare: (TRString *) dn withAttribute: (TRString *) attribute value: (TRString *) value { struct timeval timeout; LDAPMessage *res; struct berval bval; int err; int msgid; /* Set up the ber structure for our value */ bval.bv_val = (char *) [value cString]; bval.bv_len = [value length] - 1; /* Length includes NULL terminator */ /* Set up the timeout */ timeout.tv_sec = _timeout; timeout.tv_usec = 0; /* Perform the compare */ if ((err = ldap_compare_ext(ldapConn, [dn cString], [attribute cString], &bval, NULL, NULL, &msgid)) != LDAP_SUCCESS) { [TRLog debug: "LDAP compare failed: %d: %s", err, ldap_err2string(err)]; return NO; } /* Wait for the result */ if (ldap_result(ldapConn, msgid, 1, &timeout, &res) <= 0) { err = ldap_get_errno(ldapConn); if (err == LDAP_TIMEOUT) ldap_abandon_ext(ldapConn, msgid, NULL, NULL); [TRLog debug: "ldap_compare_ext failed: %s", ldap_err2string(err)]; return NO; } /* Check the result */ if (ldap_parse_result(ldapConn, res, &err, NULL, NULL, NULL, NULL, 1) != LDAP_SUCCESS) { /* Parsing failed */ return NO; } if (err == LDAP_COMPARE_TRUE) return YES; else return NO; return NO; } - (BOOL) compareDN: (TRString *) dn withAttribute: (TRString *) attribute value: (TRString *) value { struct timeval timeout; LDAPMessage *res; struct berval bval; int err; int msgid; /* Set up the ber structure for our value */ bval.bv_val = (char *) [value cString]; bval.bv_len = [value length] - 1; /* Length includes NULL terminator */ /* Set up the timeout */ timeout.tv_sec = _timeout; timeout.tv_usec = 0; /* Perform the compare */ if ((err = ldap_compare_ext(ldapConn, [dn cString], [attribute cString], &bval, NULL, NULL, &msgid)) != LDAP_SUCCESS) { [TRLog debug: "LDAP compare failed: %d: %s", err, ldap_err2string(err)]; return NO; } /* Wait for the result */ if (ldap_result(ldapConn, msgid, 1, &timeout, &res) <= 0) { err = ldap_get_errno(ldapConn); if (err == LDAP_TIMEOUT) ldap_abandon_ext(ldapConn, msgid, NULL, NULL); [TRLog debug: "ldap_compare_ext failed: %s", ldap_err2string(err)]; return NO; } /* Check the result */ if (ldap_parse_result(ldapConn, res, &err, NULL, NULL, NULL, NULL, 1) != LDAP_SUCCESS) { /* Parsing failed */ return NO; } if (err == LDAP_COMPARE_TRUE) return YES; else return NO; return NO; } - (BOOL) setReferralEnabled: (BOOL) enabled { if (enabled) return [self setLDAPOption: LDAP_OPT_REFERRALS value: LDAP_OPT_ON connection: ldapConn]; else return [self setLDAPOption: LDAP_OPT_REFERRALS value: LDAP_OPT_OFF connection: ldapConn]; } - (BOOL) setTLSCACertFile: (TRString *) fileName { if ([self setLDAPOption: LDAP_OPT_X_TLS_CACERTFILE value: [fileName cString] connection: ldapConn]) if ([self setTLSRequireCert]) return true; return false; } - (BOOL) setTLSCACertDir: (TRString *) directory { if ([self setLDAPOption: LDAP_OPT_X_TLS_CACERTDIR value: [directory cString] connection: ldapConn]) if ([self setTLSRequireCert]) return true; return false; } - (BOOL) setTLSClientCert: (TRString *) certFile keyFile: (TRString *) keyFile { if ([self setLDAPOption: LDAP_OPT_X_TLS_CERTFILE value: [certFile cString] connection: ldapConn]) if ([self setLDAPOption: LDAP_OPT_X_TLS_KEYFILE value: [keyFile cString] connection: ldapConn]) return true; return false; } - (BOOL) setTLSCipherSuite: (TRString *) cipherSuite { return [self setLDAPOption: LDAP_OPT_X_TLS_CIPHER_SUITE value: [cipherSuite cString] connection: ldapConn]; } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPEntry.h000066400000000000000000000040111332642612100217000ustar00rootroot00000000000000/* * TRLDAPEntry.h vi:ts=4:sw=4:expandtab: * LDAP Entry * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRObject.h" #import "TRString.h" #import "TRHash.h" @interface TRLDAPEntry : TRObject { @private TRString *_dn; TRString *_rdn; TRHash *_attributes; } - (id) initWithDN: (TRString *) dn attributes: (TRHash *) attributes; - (TRString *) dn; - (TRString *) rdn; - (void) setRDN: (TRString *) rdn; - (TRHash *) attributes; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPEntry.m000066400000000000000000000045751332642612100217240ustar00rootroot00000000000000/* * TRLDAPEntry.m vi:ts=4:sw=4:expandtab: * LDAP Entry * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRLDAPEntry.h" /** * An LDAP entry. */ @implementation TRLDAPEntry - (id) initWithDN: (TRString *) dn attributes: (TRHash *) attributes { self = [self init]; if (!self) return self; _dn = [dn retain]; _rdn = nil; _attributes = [attributes retain]; return self; } - (void) dealloc { [_dn release]; [_rdn release]; [_attributes release]; [super dealloc]; } /** * Returns the entry's distinguished name. */ - (TRString *) dn { return _dn; } - (TRString *) rdn { return _rdn; } - (void) setRDN: (TRString *) rdn { _rdn=rdn; } /** * Return the entries' attributes as a dictionary. */ - (TRHash *) attributes { return _attributes; } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPGroupConfig.h000066400000000000000000000046721332642612100230360ustar00rootroot00000000000000/* * TRLDAPGroupConfig.h vi:ts=4:sw=4:expandtab: * LDAP Group Configuration * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRObject.h" #import "TRString.h" @interface TRLDAPGroupConfig : TRObject { @private TRString *_baseDN; TRString *_searchFilter; TRString *_memberAttribute; BOOL _memberRFC2307BIS; BOOL _useCompareOperation; TRString *_pfTable; } - (TRString *) baseDN; - (void) setBaseDN: (TRString *) baseDN; - (TRString *) searchFilter; - (void) setSearchFilter: (TRString *) searchFilter; - (TRString *) memberAttribute; - (void) setMemberAttribute: (TRString *) memberAttribute; - (BOOL) memberRFC2307BIS; - (void) setMemberRFC2307BIS: (BOOL) memberRFC2307BIS; - (BOOL) useCompareOperation; - (void) setUseCompareOperation: (BOOL) useCompareOperation; - (TRString *) pfTable; - (void) setPFTable: (TRString *) tableName; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPGroupConfig.m000066400000000000000000000064761332642612100230470ustar00rootroot00000000000000/* * TRLDAPGroupConfig.m vi:ts=4:sw=4:expandtab: * LDAP Group Configuration * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import "TRLDAPGroupConfig.h" @implementation TRLDAPGroupConfig - (void) dealloc { if (_baseDN) [_baseDN release]; if (_searchFilter) [_searchFilter release]; if (_memberAttribute) [_memberAttribute release]; if (_pfTable) [_pfTable release]; [super dealloc]; } - (id) init { self = [super init]; if (self == nil) return self; _memberRFC2307BIS = YES; _useCompareOperation = YES; return self; } - (TRString *) baseDN { return (_baseDN); } - (void) setBaseDN: (TRString *) baseDN { if (_baseDN) [_baseDN release]; _baseDN = [baseDN retain]; } - (TRString *) searchFilter { return (_searchFilter); } - (void) setSearchFilter: (TRString *) searchFilter { if (_searchFilter) [_searchFilter release]; _searchFilter = [searchFilter retain]; } - (TRString *) memberAttribute { return (_memberAttribute); } - (void) setMemberAttribute: (TRString *) memberAttribute { if (_memberAttribute) [_memberAttribute release]; _memberAttribute = [memberAttribute retain]; } - (BOOL) memberRFC2307BIS { return (_memberRFC2307BIS); } - (void) setMemberRFC2307BIS: (BOOL) memberRFC2307BIS { _memberRFC2307BIS = memberRFC2307BIS; } - (BOOL) useCompareOperation { return (_useCompareOperation); } - (void) setUseCompareOperation: (BOOL) useCompareOperation { _useCompareOperation = useCompareOperation; } - (void) setPFTable: (TRString *) tableName { if (_pfTable) [_pfTable release]; _pfTable = [tableName retain]; } - (TRString *) pfTable { return (_pfTable); } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPSearchFilter.h000066400000000000000000000036421332642612100231630ustar00rootroot00000000000000/* * TRLDAPSearchFilter.h vi:ts=4:sw=4:expandtab: * LDAP Search Filter Generator * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRObject.h" #import "TRString.h" @interface TRLDAPSearchFilter : TRObject { @private TRString *_format; } - (id) initWithFormat: (TRString *) format; - (TRString *) getFilter: (TRString *) subString; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLDAPSearchFilter.m000066400000000000000000000123261332642612100231670ustar00rootroot00000000000000/* * TRLDAPSearchFilter.m vi:ts=4:sw=4:expandtab: * LDAP Search Filter Generator * * Author: Landon Fuller * * Copyright (c) 2005 - 2008 Landon Fuller * Copyright (c) 2007 - 2008 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRLDAPSearchFilter.h" #import "TRAutoreleasePool.h" @interface TRLDAPSearchFilter (TRLDAPSearchFilterPrivate) - (TRString *) escapeForSearch: (TRString *) string; @end @implementation TRLDAPSearchFilter /** * Initialize with the given format string. * The only valid format specifier is %s -- it will be replaced with the * provided substitute string when -[TRLDAPSearchFilter getFilter] is called. */ - (id) initWithFormat: (TRString *) format { self = [super init]; if (self == nil) return nil; _format = [format retain]; return self; } - (void) dealloc { /* Release our format string */ [_format release]; /* Deallocate superclass */ [super dealloc]; } /** * Escape the provided string according to RFC 2254, escaping * any special LDAP search characters. */ - (TRString *) escapeForSearch: (TRString *) string { const char specialChars[] = "*()\\"; /* RFC 2254. We don't care about NULL */ TRString *result = [[TRString alloc] init]; TRString *unquotedString, *part; TRAutoreleasePool *pool = [[TRAutoreleasePool alloc] init]; /* Retain an instance of the string */ unquotedString = [string retain]; /* Initialize the result */ result = [[TRString alloc] init]; /* Quote all occurrences of the special characters */ while ((part = [unquotedString substringToCharset: specialChars]) != NULL) { TRString *temp; size_t index; char c; /* Append everything until the first special character */ [result appendString: part]; /* Append the backquote */ [result appendCString: "\\"]; /* Get the special character */ index = [unquotedString indexToCharset: specialChars]; temp = [unquotedString substringFromIndex: index]; c = [temp charAtIndex: 0]; /* Append it, too! */ [result appendChar: c]; /* Move unquotedString past the special character */ temp = [[unquotedString substringFromCharset: specialChars] retain]; [unquotedString release]; unquotedString = temp; } /* Append the remainder, if any */ if (unquotedString) { [result appendString: unquotedString]; [unquotedString release]; } [pool release]; return (result); } /** * Return a search filter string, substituting all %s format * specifiers with the provided subString. */ - (TRString *) getFilter: (TRString *) subString { TRString *templateString; TRString *result, *part; TRString *quotedName; const char userFormat[] = "%s"; TRAutoreleasePool *pool = [[TRAutoreleasePool alloc] init]; /* Retain the template */ templateString = [[_format retain] autorelease]; /* Initialize the result */ result = [[TRString alloc] init]; /* Quote the sub string */ quotedName = [self escapeForSearch: subString]; while ((part = [templateString substringToCString: userFormat]) != NULL) { TRString *temp; /* Append everything until the first %u */ [result appendString: part]; /* Append the username */ [result appendString: quotedName]; /* Move templateString past the %u */ temp = [templateString substringFromCString: userFormat]; templateString = temp; } [quotedName release]; /* Append the remainder, if any */ if (templateString) { [result appendString: templateString]; } [pool release]; return [result autorelease]; } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLocalPacketFilter.h000066400000000000000000000050361332642612100234760ustar00rootroot00000000000000/* * TRLocalPacketFilter.h vi:ts=4:sw=4:expandtab: * Interface to local OpenBSD /dev/pf * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #ifdef HAVE_PF #import "TRObject.h" #import "TRPacketFilter.h" #import "TRArray.h" #import "TRPFAddress.h" #import "TRString.h" /* pf includes */ #import #import #import #import #import @interface TRLocalPacketFilter : TRObject { @private /** Cached reference to /dev/pf. */ int _fd; } - (pferror_t) open; - (void) close; - (pferror_t) tables: (TRArray **) result; - (pferror_t) flushTable: (TRString *) tableName; - (pferror_t) addAddress: (TRPFAddress *) address toTable: (TRString *) tableName; - (pferror_t) deleteAddress: (TRPFAddress *) address fromTable: (TRString *) tableName; - (pferror_t) addressesFromTable: (TRString *) tableName withResult: (TRArray **) result; @end #endif /* HAVE_PF */ openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLocalPacketFilter.m000066400000000000000000000261401332642612100235020ustar00rootroot00000000000000/* * TRLocalPacketFilter.m vi:ts=4:sw=4:expandtab: * Interface to local OpenBSD /dev/pf * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRLocalPacketFilter.h" #ifdef HAVE_PF #import #import #import #import #import #import /* Private Methods */ @interface TRLocalPacketFilter (Private) + (pferror_t) mapErrno; - (int) ioctl: (unsigned long) request withArgp: (void *) argp; - (BOOL) pfFromAddress: (TRPFAddress *) source pfaddr: (struct pfr_addr *) dest; - (TRPFAddress *) addressFromPF: (struct pfr_addr *) pfaddr; @end /** * An interface to a local OpenBSD Packet Filter. */ @implementation TRLocalPacketFilter /** * Initialize a new instance. */ - (id) init { self = [super init]; if (self == nil) return self; _fd = -1; return self; } /** * Open a reference to /dev/pf. Must be called before * any other PF methods. */ - (pferror_t) open { /* Open a reference to /dev/pf */ if ((_fd = open(PF_DEV_PATH, O_RDWR)) == -1) return [TRLocalPacketFilter mapErrno]; else return PF_SUCCESS; } /** * Close and release any open references to /dev/pf. * This is called automatically when the object is released. */ - (void) close { if (_fd != -1) { close(_fd); _fd = -1; } } - (void) dealloc { [self close]; [super dealloc]; } /** Return an array of table names */ - (pferror_t) tables: (TRArray **) result { TRArray *tables = nil; struct pfioc_table io; struct pfr_table *table; int size, i; /* Initialize the io structure */ memset(&io, 0, sizeof(io)); io.pfrio_esize = sizeof(struct pfr_table); /* First attempt with a reasonable buffer size - 32 tables */ size = sizeof(struct pfr_table) * 32; io.pfrio_buffer = xmalloc(size); /* Loop until success. */ while (1) { io.pfrio_size = size; if ([self ioctl: DIOCRGETTABLES withArgp: &io] == -1) { pferror_t ret; ret = [TRLocalPacketFilter mapErrno]; free(io.pfrio_buffer); *result = nil; return ret; } /* Do we need a larger buffer? */ if (io.pfrio_size > size) { /* Allocate the suggested space */ size = io.pfrio_size; io.pfrio_buffer = xrealloc(io.pfrio_buffer, size); } else { /* Success! Exit the loop */ break; } } /* Iterate over the returned tables, building our array */ tables = [[TRArray alloc] init]; size = io.pfrio_size / sizeof(struct pfr_table); table = (struct pfr_table *) io.pfrio_buffer; for (i = 0; i < size; i++) { TRString *name = [[TRString alloc] initWithCString: table->pfrt_name]; [tables addObject: name]; [name release]; table++; } free(io.pfrio_buffer); *result = [tables autorelease]; return PF_SUCCESS; } /** * Clear all addreses from the specified table. */ - (pferror_t) flushTable: (TRString *) tableName { struct pfioc_table io; /* Validate name */ if ([tableName length] > sizeof(io.pfrio_table.pfrt_name)) return PF_ERROR_INVALID_NAME; /* Initialize the io structure */ memset(&io, 0, sizeof(io)); /* Copy in the table name */ strcpy(io.pfrio_table.pfrt_name, [tableName cString]); /* Issue the ioctl */ if ([self ioctl: DIOCRCLRADDRS withArgp: &io] == -1) { return [TRLocalPacketFilter mapErrno]; } return PF_SUCCESS; } /** * Add an address to the specified table. */ - (pferror_t) addAddress: (TRPFAddress *) address toTable: (TRString *) tableName { struct pfioc_table io; struct pfr_addr addr; /* Validate name */ if ([tableName length] > sizeof(io.pfrio_table.pfrt_name)) return PF_ERROR_INVALID_NAME; /* Initialize the io structure */ memset(&io, 0, sizeof(io)); io.pfrio_esize = sizeof(struct pfr_addr); /* Build the request */ strcpy(io.pfrio_table.pfrt_name, [tableName cString]); if ([self pfFromAddress: address pfaddr: &addr] != true) return PF_ERROR_INTERNAL; io.pfrio_buffer = &addr; io.pfrio_size = 1; /* Issue the ioctl */ if ([self ioctl: DIOCRADDADDRS withArgp: &io] == -1) { return [TRLocalPacketFilter mapErrno]; } if (io.pfrio_nadd != 1) { return PF_ERROR_INTERNAL; } return PF_SUCCESS; } /** * Delete an address from the specified table. */ - (pferror_t) deleteAddress: (TRPFAddress *) address fromTable: (TRString *) tableName { struct pfioc_table io; struct pfr_addr addr; /* Validate name */ if ([tableName length] > sizeof(io.pfrio_table.pfrt_name)) return PF_ERROR_INVALID_NAME; /* Initialize the io structure */ memset(&io, 0, sizeof(io)); io.pfrio_esize = sizeof(struct pfr_addr); /* Build the request */ strcpy(io.pfrio_table.pfrt_name, [tableName cString]); if ([self pfFromAddress: address pfaddr: &addr] != true) return PF_ERROR_INTERNAL; io.pfrio_buffer = &addr; io.pfrio_size = 1; /* Issue the ioctl */ if ([self ioctl: DIOCRDELADDRS withArgp: &io] == -1) { return [TRLocalPacketFilter mapErrno]; } if (io.pfrio_ndel != 1) { return PF_ERROR_INTERNAL; } return PF_SUCCESS; } /** * Return an array of all addresses from the specified table. */ - (pferror_t) addressesFromTable: (TRString *) tableName withResult: (TRArray **) result { TRArray *addresses = nil; struct pfioc_table io; struct pfr_addr *pfrAddr; int size, i; /* Validate name */ if ([tableName length] > sizeof(io.pfrio_table.pfrt_name)) { *result = nil; return PF_ERROR_INVALID_NAME; } /* Initialize the io structure */ memset(&io, 0, sizeof(io)); io.pfrio_esize = sizeof(struct pfr_addr); /* Copy in the table name */ strcpy(io.pfrio_table.pfrt_name, [tableName cString]); /* First attempt with a reasonable buffer size - 32 addresses */ size = 32; io.pfrio_buffer = xmalloc(size * sizeof(struct pfr_addr)); /* Loop until success. */ while (1) { io.pfrio_size = size; if ([self ioctl: DIOCRGETADDRS withArgp: &io] == -1) { pferror_t ret; ret = [TRLocalPacketFilter mapErrno]; free(io.pfrio_buffer); *result = nil; return ret; } /* Do we need a larger buffer? */ if (io.pfrio_size > size) { /* Allocate the suggested space */ size = io.pfrio_size; io.pfrio_buffer = xrealloc(io.pfrio_buffer, size * sizeof(struct pfr_addr)); } else { /* Success! Exit the loop */ break; } } /* Iterate over the returned addresses, building our array */ addresses = [[TRArray alloc] init]; pfrAddr = (struct pfr_addr *) io.pfrio_buffer; for (i = 0; i < io.pfrio_size; i++) { TRPFAddress *address = [self addressFromPF: pfrAddr]; [addresses addObject: address]; [address release]; pfrAddr++; } free(io.pfrio_buffer); *result = [addresses autorelease]; return PF_SUCCESS; } @end /* * TRLocalPacketFilter Private Methods */ @implementation TRLocalPacketFilter (Private) /** * Map PF errno values to pferror_t values */ + (pferror_t) mapErrno { switch (errno) { case ESRCH: /* Returned when a table, etc, is not found. * "No such process" doesn't make much sense here. */ return PF_ERROR_NOT_FOUND; case EINVAL: return PF_ERROR_INVALID_ARGUMENT; case EPERM: /* Returned when /dev/pf can't be opened, and? */ return PF_ERROR_PERMISSION; default: return PF_ERROR_UNKNOWN; break; } } /* ioctl() with an extra seat-belt. */ - (int) ioctl: (unsigned long) request withArgp: (void *) argp { assert(_fd >= 0); return ioctl(_fd, request, argp); } /** * Create a new TRPFAddress address with the provided pfr_addr structure. */ - (TRPFAddress *) addressFromPF: (struct pfr_addr *) pfaddr { TRPortableAddress addr; /* Initialize the addr structure */ memset(&addr, 0, sizeof(addr)); addr.family = pfaddr->pfra_af; addr.netmask = pfaddr->pfra_net; switch (addr.family) { case (AF_INET): memcpy(&addr.ip4_addr, &pfaddr->pfra_ip4addr, sizeof(addr.ip4_addr)); break; case (AF_INET6): memcpy(&addr.ip6_addr, &pfaddr->pfra_ip6addr, sizeof(addr.ip6_addr)); break; default: [TRLog debug: "Unsupported address family: %d", addr.family]; return nil; } return [[TRPFAddress alloc] initWithPortableAddress: &addr]; } /** * Copies the address' struct pfr_addr representation * to the provided destination pointer. */ - (BOOL) pfFromAddress: (TRPFAddress *) source pfaddr: (struct pfr_addr *) dest { TRPortableAddress addr; [source address: &addr]; memset(dest, 0, sizeof(*dest)); dest->pfra_af = addr.family; dest->pfra_net = addr.netmask; switch (addr.family) { case (AF_INET): memcpy(&dest->pfra_ip4addr, &addr.ip4_addr, sizeof(dest->pfra_ip4addr)); return true; case (AF_INET6): memcpy(&dest->pfra_ip6addr, &addr.ip6_addr, sizeof(dest->pfra_ip6addr)); return true; default: /* Should be unreachable, as long as we're */ [TRLog debug: "Unsupported address family: %d", addr.family]; return false; } return false; } @end #endif /* HAVE_PF */ openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLog.h000066400000000000000000000042371332642612100206710ustar00rootroot00000000000000/* * TRLog.h vi:ts=4:sw=4:expandtab: * Simple logging interface * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRObject.h" typedef enum { TRLOG_ERR, TRLOG_WARNING, TRLOG_INFO, TRLOG_DEBUG } loglevel_t; @interface TRLog : TRObject + (void) _quiesceLogging: (BOOL) quiesce; #define DO_LOG_DECL(logName) \ /** Log a logname message */ \ + (void) logName: (const char *) message, ...; DO_LOG_DECL(error); DO_LOG_DECL(warning); DO_LOG_DECL(info); DO_LOG_DECL(debug); + (void) log: (loglevel_t) level withMessage: (const char *) message, ...; #undef DO_LOG_DECL @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRLog.m000066400000000000000000000072461332642612100207010ustar00rootroot00000000000000/* * TRLog.m vi:ts=4:sw=4:expandtab: * Simple logging interface * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import #import #import "TRLog.h" static BOOL _quiesce = NO; /** Log a message to stderr. */ static void log_stderr(const char *message, va_list args) { /* Log the message to stderr */ vfprintf(stderr, message, args); fprintf(stderr, "\n"); } /** Log a message to syslog. */ static void log_syslog(int priority, const char *message, va_list args) { vsyslog(priority, message, args); } /** * OpenVPN Auth-LDAP Logger. */ @implementation TRLog /** * Private method that quiets all logging for the purpose of unit testing. */ + (void) _quiesceLogging: (BOOL) quiesce { _quiesce = quiesce; } #define DO_LOG(logName, priority) \ /** Log a priority message. */ \ + (void) logName: (const char *) message, ... { \ va_list ap; \ if (_quiesce) return; \ va_start(ap, message); \ log_syslog(priority, message, ap); \ va_end(ap); \ va_start(ap, message); \ log_stderr(message, ap); \ va_end(ap); \ } DO_LOG(error, LOG_ERR); DO_LOG(warning, LOG_WARNING); DO_LOG(info, LOG_INFO); DO_LOG(debug, LOG_DEBUG); #undef DO_LOG /** * Log a message with the supplied priority. */ + (void) log: (loglevel_t) level withMessage: (const char *) message, ... { va_list ap; int priority = LOG_ERR; /* Logging quiesced for debugging. */ if (_quiesce) return; /* Map the TRLog log level to a syslog priority. */ switch (level) { case TRLOG_ERR: priority = LOG_ERR; break; case TRLOG_WARNING: priority = LOG_WARNING; break; case TRLOG_INFO: priority = LOG_INFO; break; case TRLOG_DEBUG: priority = LOG_DEBUG; break; } /* Log the message to syslog */ va_start(ap, message); log_syslog(priority, message, ap); va_end(ap); /* Log the message to stderr */ va_start(ap, message); log_stderr(message, ap); va_end(ap); } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRObject.h000066400000000000000000000071071332642612100213550ustar00rootroot00000000000000/* * TRObject.h vi:ts=4:sw=4:expandtab: * Project Root Class * * Author: Landon Fuller * * Copyright (c) 2007 Landon Fuller * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import #import #include #import "PXObjCRuntime.h" #import @protocol TRObject /** * Return the current object retain count. This does not take into account any enqueued autorelease calls, * and should generally not be used. */ - (PXUInteger) retainCount; /** * Retain a reference to the receiver, incrementing the reference count. */ - (id) retain; /** * Release a reference to the receiver, decrementing the reference count. If the reference count reaches zero, * the receiver will be deallocated. */ - (oneway void) release; /** * Add the object to the current autorelease pool. Objects in the autorelease * pool will be released at a later time. * @result Returns a reference to the receiver. */ - (id) autorelease; /** * Return the receiver's class. */ - (Class) class; /** * Return YES if the receiver is equal to @a anObject. * * The default implementation of this method performs a check for pointer equality. Subclasses may override this * method to check for value equality. * * @note If two objects are equal, they must also have the same hash value. */ - (BOOL) isEqual: (id) anObject; /** * Returns an unsigned integer that may be used as a table address in a hash table structure. * * The value returned by this method must not change while the object is part of a collection * that uses hash values to determine collection position. */ - (PXUInteger) hash; /** * Returns YES if the receiver is an instance of the given @a cls, or any class that inherits * from cls. * * @param cls The class against which the receiver's class will be tested. */ - (BOOL) isKindOfClass: (Class) cls; @end @interface TRObject { @private id isa; PXUInteger _refCount; } + (id) alloc; - (id) init; - (void) dealloc; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRObject.m000066400000000000000000000075731332642612100213710ustar00rootroot00000000000000/* * TRObject.m vi:ts=4:sw=4:expandtab: * Project Root Class * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import #import "TRObject.h" #import "TRAutoreleasePool.h" #import /** * Base class. Handles reference counting and equality. */ @implementation TRObject /** * Allocate a new instance of the receiver. */ + (id) alloc { return class_createInstance(self, 0); } /** * Return the receiver's class. */ + (Class) class { return self; } /** * Implemented by subclasses to initialize a newly allocated object. The default * implementation performs no initialization. */ - (id) init { _refCount = 1; return self; } /** * Called upon deallocation of the receiver. Responsible for discarding all resources held by the * receiver. * * This method will be called automatically when the receiver's reference count reaches 0. It should * never be called directly. As an exception to this, subclass implementations of -dealloc must * incorporate the superclass implementation through a message to super. */ - (void) dealloc { object_dispose(self); } // from TRObject protocol - (Class) class { return object_getClass(self); } // from TRObject protocol - (BOOL) isEqual: (id) anObject { if (self == anObject) return YES; else return NO; } // from TRObject protocol - (PXUInteger) hash { assert(sizeof(PXUInteger) >= sizeof(uintptr_t)); return (PXUInteger) self; } // from TRObject protocol - (BOOL) isKindOfClass: (Class) cls { Class selfClass = [self class]; for (Class superClass = selfClass; superClass != NULL; superClass = class_getSuperclass(superClass)) { if (superClass == cls) return YES; } return NO; } // from TRObject protocol - (PXUInteger) retainCount { return _refCount; } // from TRObject protocol - (id) retain { _refCount++; return self; } // from TRObject protocol - (oneway void) release { /* This must never occur */ assert(_refCount >= 1); /* Decrement refcount, if zero, dealloc */ _refCount--; if (!_refCount) [self dealloc]; } // from TRObject protocol - (id) autorelease { [TRAutoreleasePool addObject: self]; return self; } /* Don't auto-release the class object! */ + (id) autorelease { return self; } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRPFAddress.h000066400000000000000000000044441332642612100217630ustar00rootroot00000000000000/* * TRPFAddress.h vi:ts=4:sw=4:expandtab: * OpenBSD PF Address * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "TRObject.h" #import "TRString.h" #import #import #import #import #import typedef struct { sa_family_t family; union { struct in_addr ip4_addr; struct in6_addr ip6_addr; }; uint8_t netmask; } TRPortableAddress; @interface TRPFAddress : TRObject { @private TRPortableAddress _addr; } - (id) initWithPresentationAddress: (TRString *) address; - (id) initWithPortableAddress: (TRPortableAddress *) address; - (void) address: (TRPortableAddress *) addr; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRPFAddress.m000066400000000000000000000061121332642612100217620ustar00rootroot00000000000000/* * TRPFAddress.m vi:ts=4:sw=4:expandtab: * OpenBSD PF Address * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import "TRPFAddress.h" /** * Represents a single IPv4 or IPv6 address, for use with PF. */ @implementation TRPFAddress - (id) init { self = [super init]; if (!self) return self; /* Initialize the TRPortableAddress structure */ memset(&_addr, 0, sizeof(_addr)); return self; } /** * Initialize with an IPv4 or IPv6 address string. * @param address An IPv4 or IPv6 address in human-readable format (eg 127.0.0.1 or ::1) */ - (id) initWithPresentationAddress: (TRString *) address { if (![self init]) return nil; /* Try IPv4, then IPv6 */ if (inet_pton(AF_INET, [address cString], &_addr.ip4_addr)) { _addr.family = AF_INET; _addr.netmask = 32; return self; } else if(inet_pton(AF_INET6, [address cString], &_addr.ip6_addr)) { _addr.family = AF_INET6; _addr.netmask = 128; return self; } /* Fall through */ [self release]; return nil; } /** * Initialize from the provided TRPortableAddress representation. */ - (id) initWithPortableAddress: (TRPortableAddress *) address { if (![self init]) return nil; memcpy(&_addr, address, sizeof(_addr)); return self; } /** * Copies the address' TRPortableAddress representation * to the provided destination pointer. */ - (void) address: (TRPortableAddress *) dest { memcpy(dest, &_addr, sizeof(*dest)); } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRPacketFilter.h000066400000000000000000000106201332642612100225160ustar00rootroot00000000000000/* * TRPacketFilter.h vi:ts=4:sw=4:expandtab: * Generic interface to the OpenBSD Packet Filter * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRObject.h" #import "TRArray.h" #import "TRString.h" #import "TRPFAddress.h" typedef enum { PF_SUCCESS = 0, /* No error occured. */ PF_ERROR_NOT_FOUND = 1, /* Unknown (eg, table) name. */ PF_ERROR_INVALID_NAME = 2, /* Invalid (eg, table) name. */ PF_ERROR_UNAVAILABLE = 3, /* PF unavailable (eg, could not open /dev/pf). */ PF_ERROR_PERMISSION = 4, /* PF permission denied (eg, insufficient permissions to /dev/pf). */ PF_ERROR_INVALID_ARGUMENT = 5, /* An invalid argument was supplied. */ PF_ERROR_INTERNAL = 6, /* An internal error occured. */ PF_ERROR_UNKNOWN = 7 /* An unknown error occured. */ } pferror_t; /** * Packet Filter Class Protocol. */ @protocol TRPacketFilter /** * Open a reference to the underlying packet filter implementation. */ - (pferror_t) open; /** * Close any references to the underlying packet filter implementation, * and free any associated resources. */ - (void) close; /** * Return a list of packet filter tables in result. * @param result A pointer in which a pointer to the result array will be placed. The array will be auto-released. * @return A PF_SUCCESS on success, otherwise, a pferror_t failure code. */ - (pferror_t) tables: (TRArray **) result; /** * Flush all addresses from the specified table. * @param tableName The table to flush. * @return A PF_SUCCESS on success, otherwise, a pferror_t failure code. */ - (pferror_t) flushTable: (TRString *) tableName; /** * Add an address to the specified table. * @param address The address to add. * @param tableName The address will be added to this table. * @return A PF_SUCCESS on success, otherwise, a pferror_t failure code. */ - (pferror_t) addAddress: (TRPFAddress *) address toTable: (TRString *) tableName; /** * Delete an address from the specified table. * @param address The address to delete. * @param tableName The address will be deleted to this table. * @return A PF_SUCCESS on success, otherwise, a pferror_t failure code. */ - (pferror_t) deleteAddress: (TRPFAddress *) address fromTable: (TRString *) tableName; /** * Return a list of packet filter tables in result. * @param tableName The name from which to gather the list of addresses. * @param result A pointer in which a pointer to the result array will be placed. The array will be auto-released. * @return A PF_SUCCESS on success, otherwise, a pferror_t failure code. */ - (pferror_t) addressesFromTable: (TRString *) tableName withResult: (TRArray **) result; @end /* * Packet Filter Utility Class */ @interface TRPacketFilterUtil : TRObject + (char *) stringForError: (pferror_t) error; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRPacketFilter.m000066400000000000000000000051041332642612100225240ustar00rootroot00000000000000/* * TRLocalPacketFilter.m vi:ts=4:sw=4:expandtab: * Interface to local OpenBSD /dev/pf * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import #import #import #import #import #import "TRPacketFilter.h" /** * Packet Filter Utility Class */ @implementation TRPacketFilterUtil + (char *) stringForError: (pferror_t) error { switch (error) { case PF_SUCCESS: return "No error"; case PF_ERROR_NOT_FOUND: return "Not found"; case PF_ERROR_INVALID_NAME: return "Invalid name"; case PF_ERROR_UNAVAILABLE: return "Unavailable"; case PF_ERROR_PERMISSION: return "Permission denied"; case PF_ERROR_INVALID_ARGUMENT: return "Invalid argument"; case PF_ERROR_INTERNAL: return "Internal error"; case PF_ERROR_UNKNOWN: return "Unknown error"; } abort(); return "Unreachable"; } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRString.h000066400000000000000000000055231332642612100214150ustar00rootroot00000000000000/* * TRString.h vi:ts=4:sw=4:expandtab: * Brain-dead Dynamic Strings * * Copyright (c) 2005 - 2007 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import #import "TRObject.h" @interface TRString : TRObject { @private char *bytes; size_t numBytes; } + (TRString *) stringWithFormat: (const char *) format, ...; + (TRString *) stringWithCString: (const char *) cString; - (id) initWithFormat: (const char *) format arguments: (va_list) arguments; - (id) initWithCString: (const char *) cString; - (id) initWithString: (TRString *) string; - (id) initWithBytes: (const char *) data numBytes: (size_t) length; - (const char *) cString; - (size_t) length; - (BOOL) intValue: (int *) value; - (size_t) indexToCString: (const char *) cString; - (size_t) indexToCharset: (const char *) cString; - (char) charAtIndex: (size_t) index; - (TRString *) substringToIndex: (size_t) index; - (TRString *) substringFromIndex: (size_t) index; - (TRString *) substringToCString: (const char *) cString; - (TRString *) substringFromCString: (const char *) cString; - (TRString *) substringToCharset: (const char *) cString; - (TRString *) substringFromCharset: (const char *) cString; - (void) appendChar: (char) c; - (void) appendCString: (const char *) cString; - (void) appendString: (TRString *) string; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRString.m000066400000000000000000000234251332642612100214230ustar00rootroot00000000000000/* * TRString.m vi:ts=4:sw=4:expandtab: * Brain-dead Dynamic Strings * * Copyright (c) 2005 - 2007 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif /* HAVE_CONFIG_H */ #import #import #import #import #import #import #import "TRString.h" #import "xmalloc.h" #import "strlcpy.h" /** * OO String wrapper. */ @implementation TRString - (void) dealloc { free(bytes); [super dealloc]; } /** * Create a new string using the provided printf-style format * string and arguments. */ + (TRString *) stringWithFormat: (const char *) format, ... { va_list ap; TRString *ret; va_start(ap, format); ret = [[(TRString *)[self alloc] initWithFormat: format arguments: ap] autorelease]; va_end(ap); return ret; } /** * Create a new string using the provided C string. */ + (TRString *) stringWithCString: (const char *) cString { return [[[TRString alloc] initWithCString: cString] autorelease]; } /** * Initialize a new string using the provided printf-style format * string and arguments. */ - (id) initWithFormat: (const char *) format arguments: (va_list) arguments { char *output; int res = vasprintf(&output, format, arguments); /* Linux states that the value of 'output' is unspecified on error. FreeBSD * states that it will be NULL */ assert(res != -1 && output != NULL); self = [self initWithCString: output]; free(output); return self; } /** * Initialize with a copy of the given C string. */ - (id) initWithCString: (const char *) cString { self = [self init]; if (self != NULL) { numBytes = strlen(cString) + 1; bytes = xmalloc(numBytes); strlcpy(bytes, cString, numBytes); } return (self); } /** * Initialize with a copy of the provided TRString. */ - (id) initWithString: (TRString *) string { self = [self init]; if (self != NULL) { numBytes = [string length]; bytes = xmalloc(numBytes); strlcpy(bytes, [string cString], numBytes); } return (self); } /** * Initialize with a potentially non-NULL terminated string */ - (id) initWithBytes: (const char *) data numBytes: (size_t) length { self = [self init]; if (self != NULL) { if (data[length] != '\0') { numBytes = length + 1; bytes = xmalloc(numBytes); strncpy(bytes, data, length); bytes[length] = '\0'; } else { numBytes = length; bytes = xstrdup(data); } } return (self); } /** * Return the C string value. */ - (const char *) cString { return (bytes); } /** * Return the size in bytes. */ - (size_t) length { return (numBytes); } /** * Return a hash value for the receiver. * Hash algorithm borrowed from kazlib. */ - (unsigned long) hash { unsigned long randbox[] = { 0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U, 0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU, 0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU, 0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU, }; const char *p; unsigned int hash = 0; for (p = bytes; *p != '\0'; p++) { hash ^= randbox[(*p + hash) & 0xf]; hash = (hash << 1) | (hash >> 31); hash &= 0xffffffffU; hash ^= randbox[((*p >> 4) + hash) & 0xf]; hash = (hash << 2) | (hash >> 30); hash &= 0xffffffffU; } return hash; } /** * Store the integer value in the provided * value argument, and return true if the conversion * was successful */ - (BOOL) intValue: (int *) value { long i; char *endptr; i = strtol(bytes, &endptr, 10); if (*endptr != '\0') { *value = 0; return (false); } if (i >= INT_MAX) { *value = INT_MAX; return (false); } if (i <= INT_MIN) { *value = INT_MIN; return (false); } *value = (int) i; return (true); } /** * Append cString. */ - (void) appendCString: (const char *) cString { size_t len; if (numBytes == 0) { /* String not yet initialized */ numBytes = strlen(cString) + 1; bytes = xmalloc(numBytes); strlcpy(bytes, cString, numBytes); return; } len = strlen(cString); /* numBytes includes the NULL terminator */ numBytes = len + numBytes; bytes = xrealloc(bytes, numBytes); strncat(bytes, cString, len + 1); } /** * Append string. */ - (void) appendString: (TRString *) string { size_t len; if (numBytes == 0) { /* String not yet initialized */ numBytes = [string length]; bytes = xmalloc(numBytes); strlcpy(bytes, [string cString], numBytes); return; } len = [string length]; /* numBytes and [string length] both include the NULL terminator */ numBytes = len + numBytes - 1; bytes = xrealloc(bytes, numBytes); strncat(bytes, [string cString], len + 1); } /** * Append a single character. */ - (void) appendChar: (char) c { char s[2]; s[0] = c; s[1] = '\0'; [self appendCString: (const char *) &s]; } /** * Return the index of the first match of the given C string. */ - (size_t) indexToCString: (const char *) cString { size_t index = 0; char *p; const char *s; for (p = bytes; *p != '\0'; p++) { char *q = p; for (s = cString; *s != '\0'; s++) { if (*q == *s) { q++; continue; } else break; } if (*s == '\0') { /* Full Match */ return (index); } index++; } return (index); } /** * Return the index of the character following the first match * of the given C string. */ - (size_t) indexFromCString: (const char *) cString { size_t index = 0; char *p; const char *s; for (p = bytes; *p != '\0'; p++) { char *q = p; for (s = cString; *s != '\0'; s++) { if (*q == *s) { q++; continue; } else break; } if (*s == '\0') { /* Full Match */ index += strlen(cString); return (index); } index++; } return (index); } /** * Return the index to the first match for any character * in the given set. */ - (size_t) indexToCharset: (const char *) cString { size_t index = 0; char *p; const char *s; for (p = bytes; *p != '\0'; p++) { for (s = cString; *s != '\0'; s++) { if (*p == *s) return (index); } index++; } return (index); } - (size_t) indexFromCharset: (const char *) cString { size_t index = 0; char *p; const char *s; for (p = bytes; *p != '\0'; p++) { for (s = cString; *s != '\0'; s++) { if (*p == *s) { index++; return (index); } } index++; } return (index); } - (char) charAtIndex: (size_t) index { return (*(bytes + index)); } - (TRString *) substringToIndex: (size_t) index { TRString *string; char *cString; if (*(bytes + index) == '\0') { return (NULL); } string = [TRString alloc]; cString = xmalloc(index + 1); strlcpy(cString, bytes, index + 1); [string initWithCString: cString]; free(cString); return ([string autorelease]); } - (TRString *) substringFromIndex: (size_t) index { TRString *string; char *cString; if (*(bytes + index) == '\0') { return (NULL); } string = [TRString alloc]; cString = xmalloc(numBytes - index); strlcpy(cString, bytes + index, numBytes - index); [string initWithCString: cString]; free(cString); return ([string autorelease]); } - (TRString *) substringToCString: (const char *) cString { return ([self substringToIndex: [self indexToCString: cString]]); } - (TRString *) substringFromCString: (const char *) cString { return ([self substringFromIndex: [self indexFromCString: cString]]); } - (TRString *) substringToCharset: (const char *) cString { return ([self substringToIndex: [self indexToCharset: cString]]); } - (TRString *) substringFromCharset: (const char *) cString { return ([self substringFromIndex: [self indexFromCharset: cString]]); } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRVPNPlugin.h000066400000000000000000000046771332642612100220020ustar00rootroot00000000000000/* * TRVPNPlugin.h vi:ts=4:sw=4:expandtab: * Base Include File * * Author: Landon Fuller * * Copyright (c) 2007 Landon Fuller * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef TRVPNPLUGIN_H #define TRVPNPLUGIN_H #ifdef HAVE_CONFIG_H #import #endif #import "TRObject.h" #import "TRLog.h" #import "TRString.h" #import "TREnumerator.h" #import "TRArray.h" #import "TRAutoreleasePool.h" #import "TRHash.h" #import "xmalloc.h" #import "TRAccountRepository.h" #import "TRVPNSession.h" #import "TRConfigToken.h" #import "TRConfig.h" #import "TRConfigParser.h" #import "TRAuthLDAPConfig.h" #import "TRConfigLexer.h" #import "TRLDAPGroupConfig.h" #import "TRLDAPConnection.h" #import "TRLDAPEntry.h" #import "TRLDAPSearchFilter.h" #import "TRLDAPAccountRepository.h" #import "TRPFAddress.h" #import "TRPacketFilter.h" #import "TRLocalPacketFilter.h" #endif /* TRVPNPLUGIN_H */ openvpn-auth-ldap-auth-ldap-2.0.4/src/TRVPNSession.h000066400000000000000000000035731332642612100221610ustar00rootroot00000000000000/* * TRVPNSession.h vi:ts=4:sw=4:expandtab: * An active VPN session * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRObject.h" #import "TRString.h" @interface TRVPNSession: TRObject { @private TRString *_username; } - (id) initWithUsername: (TRString *) username; - (TRString *) username; @end openvpn-auth-ldap-auth-ldap-2.0.4/src/TRVPNSession.m000066400000000000000000000040531332642612100221600ustar00rootroot00000000000000/* * TRVPNSession.m vi:ts=4:sw=4:expandtab: * An active VPN session * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import "TRVPNSession.h" /** * VPN session state. */ @implementation TRVPNSession - (id) initWithUsername: (TRString *) username { self = [self init]; if (!self) return nil; _username = [username retain]; return (self); } - (void) dealloc { [_username release]; [super dealloc]; } - (TRString *) username { return (_username); } @end openvpn-auth-ldap-auth-ldap-2.0.4/src/asprintf.c000066400000000000000000000000001332642612100215030ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/src/auth-ldap.m000066400000000000000000000463261332642612100215730ustar00rootroot00000000000000/* * auth_ldap.m vi:ts=4:sw=4:expandtab: * OpenVPN LDAP Authentication Plugin * * Copyright (c) 2005 - 2007 Landon Fuller * Copyright (c) 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #import #import #import #import #import #import #import #import #include "openvpn-cr.h" /* Plugin Context */ typedef struct ldap_ctx { TRAuthLDAPConfig *config; #ifdef HAVE_PF id pf; #endif } ldap_ctx; static const char *get_env(const char *key, const char *env[]) { int i; if (!env) return (NULL); for (i = 0; env[i]; i++) { size_t keylen = strlen(key); if (keylen > strlen(env[i])) continue; if (!strncmp(key, env[i], keylen)) { const char *p = env[i] + keylen; if (*p == '=') return (p + 1); } } return (NULL); } static TRString *quoteForSearch(const char *string) { const char specialChars[] = "*()\\"; /* RFC 2254. We don't care about NULL */ TRString *result = [[TRString alloc] init]; TRString *unquotedString, *part; TRAutoreleasePool *pool = [[TRAutoreleasePool alloc] init]; /* Make a copy of the string */ unquotedString = [[TRString alloc] initWithCString: string]; /* Initialize the result */ result = [[TRString alloc] init]; /* Quote all occurrences of the special characters */ while ((part = [unquotedString substringToCharset: specialChars]) != NULL) { TRString *temp; size_t index; char c; /* Append everything until the first special character */ [result appendString: part]; /* Append the backquote */ [result appendCString: "\\"]; /* Get the special character */ index = [unquotedString indexToCharset: specialChars]; temp = [unquotedString substringFromIndex: index]; c = [temp charAtIndex: 0]; /* Append it, too! */ [result appendChar: c]; /* Move unquotedString past the special character */ temp = [[unquotedString substringFromCharset: specialChars] retain]; [unquotedString release]; unquotedString = temp; } /* Append the remainder, if any */ if (unquotedString) { [result appendString: unquotedString]; [unquotedString release]; } [pool release]; return (result); } static TRString *createSearchFilter(TRString *template, const char *username) { TRString *templateString; TRString *result, *part; TRString *quotedName; const char userFormat[] = "%u"; TRAutoreleasePool *pool = [[TRAutoreleasePool alloc] init]; /* Copy the template */ templateString = [[[TRString alloc] initWithString: template] autorelease]; /* Initialize the result */ result = [[TRString alloc] init]; /* Quote the username */ quotedName = quoteForSearch(username); while ((part = [templateString substringToCString: userFormat]) != NULL) { TRString *temp; /* Append everything until the first %u */ [result appendString: part]; /* Append the username */ [result appendString: quotedName]; /* Move templateString past the %u */ temp = [templateString substringFromCString: userFormat]; templateString = temp; } [quotedName release]; /* Append the remainder, if any */ if (templateString) { [result appendString: templateString]; } [pool release]; return (result); } #ifdef HAVE_PF static BOOL pf_open(struct ldap_ctx *ctx) { TRString *tableName; TRLDAPGroupConfig *groupConfig; TREnumerator *groupIter; pferror_t pferror; /* Acquire a reference to /dev/pf */ ctx->pf = [[TRLocalPacketFilter alloc] init]; if ((pferror = [ctx->pf open]) != PF_SUCCESS) { /* /dev/pf could not be opened. Is it available? */ [TRLog error: "Failed to open /dev/pf: %s", [TRPacketFilterUtil stringForError: pferror]]; ctx->pf = nil; return NO; } /* Clear out all referenced PF tables */ if ((tableName = [ctx->config pfTable])) { if ((pferror = [ctx->pf flushTable: tableName]) != PF_SUCCESS) { [TRLog error: "Failed to clear packet filter table \"%s\": %s", [tableName cString], [TRPacketFilterUtil stringForError: pferror]]; goto error; } } if ([ctx->config ldapGroups]) { groupIter = [[ctx->config ldapGroups] objectEnumerator]; while ((groupConfig = [groupIter nextObject]) != nil) { if ((tableName = [groupConfig pfTable])) { if ((pferror = [ctx->pf flushTable: tableName]) != PF_SUCCESS) { [TRLog error: "Failed to clear packet filter table \"%s\": %s", [tableName cString], [TRPacketFilterUtil stringForError: pferror]]; goto error; } } } } return YES; error: [ctx->pf release]; ctx->pf = NULL; return NO; } #endif /* HAVE_PF */ OPENVPN_EXPORT openvpn_plugin_handle_t openvpn_plugin_open_v1(unsigned int *type, const char *argv[], const char *envp[]) { ldap_ctx *ctx = xmalloc(sizeof(ldap_ctx)); /* Read the configuration */ ctx->config = [[TRAuthLDAPConfig alloc] initWithConfigFile: argv[1]]; if (!ctx->config) { free(ctx); return (NULL); } #ifdef HAVE_PF ctx->pf = NULL; /* Open reference to /dev/pf and clear out all of our PF tables */ if ([ctx->config pfEnabled] && !pf_open(ctx)) { [ctx->config release]; free(ctx); return (NULL); } #endif *type = OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY) | OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_CONNECT) | OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_DISCONNECT); return (ctx); } OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle) { ldap_ctx *ctx = handle; /* Clean up the configuration file */ [ctx->config release]; /* Clean up PF */ #ifdef HAVE_PF if (ctx->pf) [ctx->pf release]; #endif /* Finished */ free(ctx); } TRLDAPConnection *connect_ldap(TRAuthLDAPConfig *config) { TRLDAPConnection *ldap; TRString *value; /* Initialize our LDAP Connection */ ldap = [[TRLDAPConnection alloc] initWithURL: [config url] timeout: [config timeout]]; if (!ldap) { [TRLog error: "Unable to open LDAP connection to %s\n", [[config url] cString]]; return nil; } /* Referrals */ if ([config referralEnabled]) { if (![ldap setReferralEnabled: YES]) goto error; } else { if (![ldap setReferralEnabled: NO]) goto error; } /* Certificate file */ if ((value = [config tlsCACertFile])) if (![ldap setTLSCACertFile: value]) goto error; /* Certificate directory */ if ((value = [config tlsCACertDir])) if (![ldap setTLSCACertDir: value]) goto error; /* Client Certificate Pair */ if ([config tlsCertFile] && [config tlsKeyFile]) if(![ldap setTLSClientCert: [config tlsCertFile] keyFile: [config tlsKeyFile]]) goto error; /* Cipher suite */ if ((value = [config tlsCipherSuite])) if(![ldap setTLSCipherSuite: value]) goto error; /* Start TLS */ if ([config tlsEnabled]) if (![ldap startTLS]) goto error; /* Bind if requested */ if ([config bindDN]) { if (![ldap bindWithDN: [config bindDN] password: [config bindPassword]]) { [TRLog error: "Unable to bind as %s", [[config bindDN] cString]]; goto error; } } return ldap; error: [ldap release]; return nil; } static TRLDAPEntry *find_ldap_user (TRLDAPConnection *ldap, TRAuthLDAPConfig *config, const char *username) { TRString *searchFilter; TRArray *ldapEntries; TRLDAPEntry *result = nil; /* Assemble our search filter */ searchFilter = createSearchFilter([config searchFilter], username); /* Search! */ ldapEntries = [ldap searchWithFilter: searchFilter scope: LDAP_SCOPE_SUBTREE baseDN: [config baseDN] attributes: NULL]; [searchFilter release]; if (!ldapEntries) return nil; if ([ldapEntries count] < 1) { return nil; } /* The specified search string may (but should not) return more than one entry. * We ignore any extras. */ result = [[ldapEntries lastObject] retain]; return result; } static BOOL auth_ldap_user(TRLDAPConnection *ldap, TRAuthLDAPConfig *config, TRLDAPEntry *ldapUser, const char *password) { TRLDAPConnection *authConn; TRString *passwordString; BOOL result = NO; /* Create a second connection for binding */ authConn = connect_ldap(config); if (!authConn) { return NO; } /* Allocate the string to pass to bindWithDN */ passwordString = [[TRString alloc] initWithCString: password]; if ([authConn bindWithDN: [ldapUser dn] password: passwordString]) { result = YES; } [passwordString release]; [authConn release]; return result; } static TRLDAPGroupConfig *find_ldap_group(TRLDAPConnection *ldap, TRAuthLDAPConfig *config, TRLDAPEntry *ldapUser) { TREnumerator *groupIter; TRLDAPGroupConfig *groupConfig; TRArray *ldapEntries; TREnumerator *entryIter; TRLDAPEntry *entry; TRLDAPGroupConfig *result = nil; int userNameLength; /* * Groups are loaded into the array in the order that they are listed * in the configuration file, and we are expected to perform * "first match". Thusly, we'll walk the stack from the bottom up. */ groupIter = [[config ldapGroups] objectReverseEnumerator]; while ((groupConfig = [groupIter nextObject]) != nil) { /* Search for the group */ ldapEntries = [ldap searchWithFilter: [groupConfig searchFilter] scope: LDAP_SCOPE_SUBTREE baseDN: [groupConfig baseDN] attributes: NULL]; /* Error occured, all stop */ if (!ldapEntries) break; /* If RFC2307BIS flag is true, search for full DN, otherwise just search for uid */ TRString *searchValue = [groupConfig memberRFC2307BIS] ? [ldapUser dn] : [ldapUser rdn]; /* This will be used if we're using the "search" operation instead of the "compare" operation */ TRString *searchFilter = [TRString stringWithFormat: "(%s=%s)", [[groupConfig memberAttribute] cString], [searchValue cString]]; /* Iterate over the returned entries */ entryIter = [ldapEntries objectEnumerator]; while ((entry = [entryIter nextObject]) != nil) { if ((![groupConfig useCompareOperation] && [ldap searchWithFilter: searchFilter scope: LDAP_SCOPE_SUBTREE baseDN: [entry dn] attributes: NULL]) || ([groupConfig useCompareOperation] && [ldap compareDN: [entry dn] withAttribute: [groupConfig memberAttribute] value: searchValue])) { /* Group match! */ result = groupConfig; } } if (result) break; } return result; } /** Handle user authentication. */ static int handle_auth_user_pass_verify(ldap_ctx *ctx, TRLDAPConnection *ldap, TRLDAPEntry *ldapUser, const char *password) { TRLDAPGroupConfig *groupConfig; const char *auth_password = password; if ([ctx->config passWordIsCR]) { openvpn_response resp; char *parse_error; if (!extract_openvpn_cr(password, &resp, &parse_error)) { [TRLog error: "Error extracting challenge/response from password. Parse error = '%s'", parse_error]; return (OPENVPN_PLUGIN_FUNC_ERROR); } auth_password = (const char*)resp.password; } /* Authenticate the user */ if (!auth_ldap_user(ldap, ctx->config, ldapUser, auth_password)) { [TRLog error: "Incorrect password supplied for LDAP DN \"%s\".", [[ldapUser dn] cString]]; return (OPENVPN_PLUGIN_FUNC_ERROR); } /* User authenticated, find group, if any */ if ([ctx->config ldapGroups]) { groupConfig = find_ldap_group(ldap, ctx->config, ldapUser); if (!groupConfig && [ctx->config requireGroup]) { /* No group match, and group membership is required */ return OPENVPN_PLUGIN_FUNC_ERROR; } else { /* Group match! */ return OPENVPN_PLUGIN_FUNC_SUCCESS; } } else { // No groups, user OK return OPENVPN_PLUGIN_FUNC_SUCCESS; } /* Never reached */ return OPENVPN_PLUGIN_FUNC_ERROR; } #ifdef HAVE_PF /* Add (or remove) the remote address */ static BOOL pf_client_connect_disconnect(struct ldap_ctx *ctx, TRString *tableName, const char *remoteAddress, BOOL connecting) { TRString *addressString; TRPFAddress *address; pferror_t pferror; addressString = [[TRString alloc] initWithCString: remoteAddress]; address = [[TRPFAddress alloc] initWithPresentationAddress: addressString]; [addressString release]; if (connecting) { [TRLog debug: "Adding address \"%s\" to packet filter table \"%s\".", remoteAddress, [tableName cString]]; if ((pferror = [ctx->pf addAddress: address toTable: tableName]) != PF_SUCCESS) { [TRLog error: "Failed to add address \"%s\" to table \"%s\": %s", remoteAddress, [tableName cString], [TRPacketFilterUtil stringForError: pferror]]; [address release]; return NO; } } else { [TRLog debug: "Removing address \"%s\" from packet filter table \"%s\".", remoteAddress, [tableName cString]]; if ((pferror = [ctx->pf deleteAddress: address fromTable: tableName]) != PF_SUCCESS) { [TRLog error: "Failed to remove address \"%s\" from table \"%s\": %s", remoteAddress, [tableName cString], [TRPacketFilterUtil stringForError: pferror]]; [address release]; return NO; } } [address release]; return YES; } #endif /* HAVE_PF */ /** Handle both connection and disconnection events. */ static int handle_client_connect_disconnect(ldap_ctx *ctx, TRLDAPConnection *ldap, TRLDAPEntry *ldapUser, const char *remoteAddress, BOOL connecting) { TRLDAPGroupConfig *groupConfig = nil; #ifdef HAVE_PF TRString *tableName = nil; #endif /* Locate the group (config), if any */ if ([ctx->config ldapGroups]) { groupConfig = find_ldap_group(ldap, ctx->config, ldapUser); if (!groupConfig && [ctx->config requireGroup]) { [TRLog error: "No matching LDAP group found for user DN \"%s\", and group membership is required.", [[ldapUser dn] cString]]; /* No group match, and group membership is required */ return OPENVPN_PLUGIN_FUNC_ERROR; } } #ifdef HAVE_PF /* Grab the requested PF table name, if any */ if (groupConfig) { tableName = [groupConfig pfTable]; } else { tableName = [ctx->config pfTable]; } if (tableName) if (!pf_client_connect_disconnect(ctx, tableName, remoteAddress, connecting)) return OPENVPN_PLUGIN_FUNC_ERROR; #endif /* HAVE_PF */ return OPENVPN_PLUGIN_FUNC_SUCCESS; } OPENVPN_EXPORT int openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[]) { const char *username, *password, *remoteAddress; ldap_ctx *ctx = handle; TRLDAPConnection *ldap = nil; TRLDAPEntry *ldapUser = nil; TRAutoreleasePool *pool = nil; int ret = OPENVPN_PLUGIN_FUNC_ERROR; /* Per-request allocation pool. */ pool = [[TRAutoreleasePool alloc] init]; username = get_env("username", envp); TRString *userName=[[TRString alloc]initWithCString: username]; password = get_env("password", envp); remoteAddress = get_env("ifconfig_pool_remote_ip", envp); /* At the very least, we need a username to work with */ if (!username) { [TRLog debug: "No remote username supplied to OpenVPN LDAP Plugin."]; goto cleanup; } /* Create an LDAP connection */ if (!(ldap = connect_ldap(ctx->config))) { [TRLog error: "LDAP connect failed."]; goto cleanup; } /* Find the user record */ ldapUser = find_ldap_user(ldap, ctx->config, username); [ldapUser setRDN: userName]; if (!ldapUser) { /* No such user. */ [TRLog warning: "LDAP user \"%s\" was not found.", username]; goto cleanup; } switch (type) { /* Password Authentication */ case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY: if (!password) { [TRLog debug: "No remote password supplied to OpenVPN LDAP Plugin (OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)."]; } else { ret = handle_auth_user_pass_verify(ctx, ldap, ldapUser, password); } break; /* New connection established */ case OPENVPN_PLUGIN_CLIENT_CONNECT: if (!remoteAddress) { [TRLog debug: "No remote address supplied to OpenVPN LDAP Plugin (OPENVPN_PLUGIN_CLIENT_CONNECT)."]; } else { ret = handle_client_connect_disconnect(ctx, ldap, ldapUser, remoteAddress, YES); } break; case OPENVPN_PLUGIN_CLIENT_DISCONNECT: if (!remoteAddress) { [TRLog debug: "No remote address supplied to OpenVPN LDAP Plugin (OPENVPN_PLUGIN_CLIENT_DISCONNECT)."]; } else { ret = handle_client_connect_disconnect(ctx, ldap, ldapUser, remoteAddress, NO); } break; default: [TRLog debug: "Unhandled plugin type in OpenVPN LDAP Plugin (type=%d)", type]; break; } cleanup: if (ldapUser != nil) [ldapUser release]; if (ldap != nil) [ldap release]; if (pool != nil) [pool release]; return (ret); } openvpn-auth-ldap-auth-ldap-2.0.4/src/base64.c000066400000000000000000000174461332642612100207670ustar00rootroot00000000000000/* * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* ==================================================================== * Copyright (c) 1995-1999 The Apache Group. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * 4. The names "Apache Server" and "Apache Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Group and was originally based * on public domain software written at the National Center for * Supercomputing Applications, University of Illinois, Urbana-Champaign. * For more information on the Apache Group and the Apache HTTP server * project, please see . * */ /* Base64 encoder/decoder. Originally Apache file ap_base64.c */ #include #include "base64.h" /* aaaack but it's fast and const should make it shared text page. */ static const unsigned char pr2six[256] = { /* ASCII table */ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 }; int Base64decode_len(const char *bufcoded) { int nbytesdecoded; register const unsigned char *bufin; register int nprbytes; bufin = (const unsigned char *) bufcoded; while (pr2six[*(bufin++)] <= 63); nprbytes = (bufin - (const unsigned char *) bufcoded) - 1; nbytesdecoded = ((nprbytes + 3) / 4) * 3; return nbytesdecoded + 1; } int Base64decode(char *bufplain, const char *bufcoded) { int nbytesdecoded; register const unsigned char *bufin; register unsigned char *bufout; register int nprbytes; bufin = (const unsigned char *) bufcoded; while (pr2six[*(bufin++)] <= 63); nprbytes = (bufin - (const unsigned char *) bufcoded) - 1; nbytesdecoded = ((nprbytes + 3) / 4) * 3; bufout = (unsigned char *) bufplain; bufin = (const unsigned char *) bufcoded; while (nprbytes > 4) { *(bufout++) = (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); *(bufout++) = (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); *(bufout++) = (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); bufin += 4; nprbytes -= 4; } /* Note: (nprbytes == 1) would be an error, so just ingore that case */ if (nprbytes > 1) { *(bufout++) = (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); } if (nprbytes > 2) { *(bufout++) = (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); } if (nprbytes > 3) { *(bufout++) = (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); } *(bufout++) = '\0'; nbytesdecoded -= (4 - nprbytes) & 3; return nbytesdecoded; } static const char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int Base64encode_len(int len) { return ((len + 2) / 3 * 4) + 1; } int Base64encode(char *encoded, const char *string, int len) { int i; char *p; p = encoded; for (i = 0; i < len - 2; i += 3) { *p++ = basis_64[(string[i] >> 2) & 0x3F]; *p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0) >> 4)]; *p++ = basis_64[((string[i + 1] & 0xF) << 2) | ((int) (string[i + 2] & 0xC0) >> 6)]; *p++ = basis_64[string[i + 2] & 0x3F]; } if (i < len) { *p++ = basis_64[(string[i] >> 2) & 0x3F]; if (i == (len - 1)) { *p++ = basis_64[((string[i] & 0x3) << 4)]; *p++ = '='; } else { *p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0) >> 4)]; *p++ = basis_64[((string[i + 1] & 0xF) << 2)]; } *p++ = '='; } *p++ = '\0'; return p - encoded; } openvpn-auth-ldap-auth-ldap-2.0.4/src/base64.h000066400000000000000000000102231332642612100207560ustar00rootroot00000000000000/* * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* ==================================================================== * Copyright (c) 1995-1999 The Apache Group. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * 4. The names "Apache Server" and "Apache Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the Apache Group * for use in the Apache HTTP server project (http://www.apache.org/)." * * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Group and was originally based * on public domain software written at the National Center for * Supercomputing Applications, University of Illinois, Urbana-Champaign. * For more information on the Apache Group and the Apache HTTP server * project, please see . * */ #ifndef _BASE64_H_ #define _BASE64_H_ #ifdef __cplusplus extern "C" { #endif int Base64encode_len(int len); int Base64encode(char * coded_dst, const char *plain_src,int len_plain_src); int Base64decode_len(const char * coded_src); int Base64decode(char * plain_dst, const char *coded_src); #ifdef __cplusplus } #endif #endif //_BASE64_H_ openvpn-auth-ldap-auth-ldap-2.0.4/src/hash.c000066400000000000000000000671361332642612100206270ustar00rootroot00000000000000/* * Hash Table Data Type vi:ts=4:sw=4:expandtab: * Copyright (C) 1997 Kaz Kylheku * * Free Software License: * * All rights are reserved by the author, with the following exceptions: * Permission is granted to freely reproduce and distribute this software, * possibly in exchange for a fee, provided that this copyright notice appears * intact. Permission is also granted to adapt this software to produce * derivative works, as long as the modified versions carry this copyright * notice and additional notices stating that the work has been modified. * This source code may be translated into executable form and incorporated * into proprietary software; there is no requirement for such software to * contain a copyright notice related to this source. * * $Id: hash.c,v 1.36.2.11 2000/11/13 01:36:45 kaz Exp $ * $Name: kazlib_1_20 $ */ #include #include #include #include #define HASH_IMPLEMENTATION #include "hash.h" #ifdef KAZLIB_RCSID static const char rcsid[] = "$Id: hash.c,v 1.36.2.11 2000/11/13 01:36:45 kaz Exp $"; #endif #define INIT_BITS 6 #define INIT_SIZE (1UL << (INIT_BITS)) /* must be power of two */ #define INIT_MASK ((INIT_SIZE) - 1) #define next hash_next #define key hash_key #define data hash_data #define hkey hash_hkey #define table hash_table #define nchains hash_nchains #define nodecount hash_nodecount #define maxcount hash_maxcount #define highmark hash_highmark #define lowmark hash_lowmark #define compare hash_compare #define function hash_function #define allocnode hash_allocnode #define freenode hash_freenode #define context hash_context #define mask hash_mask #define dynamic hash_dynamic #define table hash_table #define chain hash_chain static hnode_t *hnode_alloc(void *context); static void hnode_free(hnode_t *node, void *context); static hash_val_t hash_fun_default(const void *key); static int hash_comp_default(const void *key1, const void *key2); static int hash_val_t_bit; /* * Compute the number of bits in the hash_val_t type. We know that hash_val_t * is an unsigned integral type. Thus the highest value it can hold is a * Mersenne number (power of two, less one). We initialize a hash_val_t * object with this value and then shift bits out one by one while counting. * Notes: * 1. HASH_VAL_T_MAX is a Mersenne number---one that is one less than a power * of two. This means that its binary representation consists of all one * bits, and hence ``val'' is initialized to all one bits. * 2. While bits remain in val, we increment the bit count and shift it to the * right, replacing the topmost bit by zero. */ static void compute_bits(void) { hash_val_t val = HASH_VAL_T_MAX; /* 1 */ int bits = 0; while (val) { /* 2 */ bits++; val >>= 1; } hash_val_t_bit = bits; } /* * Verify whether the given argument is a power of two. */ static int is_power_of_two(hash_val_t arg) { if (arg == 0) return 0; while ((arg & 1) == 0) arg >>= 1; return (arg == 1); } /* * Compute a shift amount from a given table size */ static hash_val_t compute_mask(hashcount_t size) { assert (is_power_of_two(size)); assert (size >= 2); return size - 1; } /* * Initialize the table of pointers to null. */ static void clear_table(hash_t *hash) { hash_val_t i; for (i = 0; i < hash->nchains; i++) hash->table[i] = NULL; } /* * Double the size of a dynamic table. This works as follows. Each chain splits * into two adjacent chains. The shift amount increases by one, exposing an * additional bit of each hashed key. For each node in the original chain, the * value of this newly exposed bit will decide which of the two new chains will * receive the node: if the bit is 1, the chain with the higher index will have * the node, otherwise the lower chain will receive the node. In this manner, * the hash table will continue to function exactly as before without having to * rehash any of the keys. * Notes: * 1. Overflow check. * 2. The new number of chains is twice the old number of chains. * 3. The new mask is one bit wider than the previous, revealing a * new bit in all hashed keys. * 4. Allocate a new table of chain pointers that is twice as large as the * previous one. * 5. If the reallocation was successful, we perform the rest of the growth * algorithm, otherwise we do nothing. * 6. The exposed_bit variable holds a mask with which each hashed key can be * AND-ed to test the value of its newly exposed bit. * 7. Now loop over each chain in the table and sort its nodes into two * chains based on the value of each node's newly exposed hash bit. * 8. The low chain replaces the current chain. The high chain goes * into the corresponding sister chain in the upper half of the table. * 9. We have finished dealing with the chains and nodes. We now update * the various bookeeping fields of the hash structure. */ static void grow_table(hash_t *hash) { hnode_t **newtable; assert (2 * hash->nchains > hash->nchains); /* 1 */ newtable = realloc(hash->table, sizeof *newtable * hash->nchains * 2); /* 4 */ if (newtable) { /* 5 */ hash_val_t mask = (hash->mask << 1) | 1; /* 3 */ hash_val_t exposed_bit = mask ^ hash->mask; /* 6 */ hash_val_t chain; assert (mask != hash->mask); for (chain = 0; chain < hash->nchains; chain++) { /* 7 */ hnode_t *low_chain = 0, *high_chain = 0, *hptr, *next; for (hptr = newtable[chain]; hptr != 0; hptr = next) { next = hptr->next; if (hptr->hkey & exposed_bit) { hptr->next = high_chain; high_chain = hptr; } else { hptr->next = low_chain; low_chain = hptr; } } newtable[chain] = low_chain; /* 8 */ newtable[chain + hash->nchains] = high_chain; } hash->table = newtable; /* 9 */ hash->mask = mask; hash->nchains *= 2; hash->lowmark *= 2; hash->highmark *= 2; } assert (hash_verify(hash)); } /* * Cut a table size in half. This is done by folding together adjacent chains * and populating the lower half of the table with these chains. The chains are * simply spliced together. Once this is done, the whole table is reallocated * to a smaller object. * Notes: * 1. It is illegal to have a hash table with one slot. This would mean that * hash->shift is equal to hash_val_t_bit, an illegal shift value. * Also, other things could go wrong, such as hash->lowmark becoming zero. * 2. Looping over each pair of sister chains, the low_chain is set to * point to the head node of the chain in the lower half of the table, * and high_chain points to the head node of the sister in the upper half. * 3. The intent here is to compute a pointer to the last node of the * lower chain into the low_tail variable. If this chain is empty, * low_tail ends up with a null value. * 4. If the lower chain is not empty, we simply tack the upper chain onto it. * If the upper chain is a null pointer, nothing happens. * 5. Otherwise if the lower chain is empty but the upper one is not, * If the low chain is empty, but the high chain is not, then the * high chain is simply transferred to the lower half of the table. * 6. Otherwise if both chains are empty, there is nothing to do. * 7. All the chain pointers are in the lower half of the table now, so * we reallocate it to a smaller object. This, of course, invalidates * all pointer-to-pointers which reference into the table from the * first node of each chain. * 8. Though it's unlikely, the reallocation may fail. In this case we * pretend that the table _was_ reallocated to a smaller object. * 9. Finally, update the various table parameters to reflect the new size. */ static void shrink_table(hash_t *hash) { hash_val_t chain, nchains; hnode_t **newtable, *low_tail, *low_chain, *high_chain; assert (hash->nchains >= 2); /* 1 */ nchains = hash->nchains / 2; for (chain = 0; chain < nchains; chain++) { low_chain = hash->table[chain]; /* 2 */ high_chain = hash->table[chain + nchains]; for (low_tail = low_chain; low_tail && low_tail->next; low_tail = low_tail->next) ; /* 3 */ if (low_chain != 0) /* 4 */ low_tail->next = high_chain; else if (high_chain != 0) /* 5 */ hash->table[chain] = high_chain; else assert (hash->table[chain] == NULL); /* 6 */ } newtable = realloc(hash->table, sizeof *newtable * nchains); /* 7 */ if (newtable) /* 8 */ hash->table = newtable; hash->mask >>= 1; /* 9 */ hash->nchains = nchains; hash->lowmark /= 2; hash->highmark /= 2; assert (hash_verify(hash)); } /* * Create a dynamic hash table. Both the hash table structure and the table * itself are dynamically allocated. Furthermore, the table is extendible in * that it will automatically grow as its load factor increases beyond a * certain threshold. * Notes: * 1. If the number of bits in the hash_val_t type has not been computed yet, * we do so here, because this is likely to be the first function that the * user calls. * 2. Allocate a hash table control structure. * 3. If a hash table control structure is successfully allocated, we * proceed to initialize it. Otherwise we return a null pointer. * 4. We try to allocate the table of hash chains. * 5. If we were able to allocate the hash chain table, we can finish * initializing the hash structure and the table. Otherwise, we must * backtrack by freeing the hash structure. * 6. INIT_SIZE should be a power of two. The high and low marks are always set * to be twice the table size and half the table size respectively. When the * number of nodes in the table grows beyond the high size (beyond load * factor 2), it will double in size to cut the load factor down to about * about 1. If the table shrinks down to or beneath load factor 0.5, * it will shrink, bringing the load up to about 1. However, the table * will never shrink beneath INIT_SIZE even if it's emptied. * 7. This indicates that the table is dynamically allocated and dynamically * resized on the fly. A table that has this value set to zero is * assumed to be statically allocated and will not be resized. * 8. The table of chains must be properly reset to all null pointers. */ hash_t *hash_create(hashcount_t maxcount, hash_comp_t compfun, hash_fun_t hashfun) { hash_t *hash; if (hash_val_t_bit == 0) /* 1 */ compute_bits(); hash = malloc(sizeof *hash); /* 2 */ if (hash) { /* 3 */ hash->table = malloc(sizeof *hash->table * INIT_SIZE); /* 4 */ if (hash->table) { /* 5 */ hash->nchains = INIT_SIZE; /* 6 */ hash->highmark = INIT_SIZE * 2; hash->lowmark = INIT_SIZE / 2; hash->nodecount = 0; hash->maxcount = maxcount; hash->compare = compfun ? compfun : hash_comp_default; hash->function = hashfun ? hashfun : hash_fun_default; hash->allocnode = hnode_alloc; hash->freenode = hnode_free; hash->context = NULL; hash->mask = INIT_MASK; hash->dynamic = 1; /* 7 */ clear_table(hash); /* 8 */ assert (hash_verify(hash)); return hash; } free(hash); } return NULL; } /* * Select a different set of node allocator routines. */ void hash_set_allocator(hash_t *hash, hnode_alloc_t al, hnode_free_t fr, void *context) { assert (hash_count(hash) == 0); assert ((al == 0 && fr == 0) || (al != 0 && fr != 0)); hash->allocnode = al ? al : hnode_alloc; hash->freenode = fr ? fr : hnode_free; hash->context = context; } /* * Free every node in the hash using the hash->freenode() function pointer, and * cause the hash to become empty. */ void hash_free_nodes(hash_t *hash) { hscan_t hs; hnode_t *node; hash_scan_begin(&hs, hash); while ((node = hash_scan_next(&hs))) { hash_scan_delete(hash, node); hash->freenode(node, hash->context); } hash->nodecount = 0; clear_table(hash); } /* * Obsolescent function for removing all nodes from a table, * freeing them and then freeing the table all in one step. */ void hash_free(hash_t *hash) { #ifdef KAZLIB_OBSOLESCENT_DEBUG assert ("call to obsolescent function hash_free()" && 0); #endif hash_free_nodes(hash); hash_destroy(hash); } /* * Free a dynamic hash table structure. */ void hash_destroy(hash_t *hash) { assert (hash_val_t_bit != 0); assert (hash_isempty(hash)); free(hash->table); free(hash); } /* * Initialize a user supplied hash structure. The user also supplies a table of * chains which is assigned to the hash structure. The table is static---it * will not grow or shrink. * 1. See note 1. in hash_create(). * 2. The user supplied array of pointers hopefully contains nchains nodes. * 3. See note 7. in hash_create(). * 4. We must dynamically compute the mask from the given power of two table * size. * 5. The user supplied table can't be assumed to contain null pointers, * so we reset it here. */ hash_t *hash_init(hash_t *hash, hashcount_t maxcount, hash_comp_t compfun, hash_fun_t hashfun, hnode_t **table, hashcount_t nchains) { if (hash_val_t_bit == 0) /* 1 */ compute_bits(); assert (is_power_of_two(nchains)); hash->table = table; /* 2 */ hash->nchains = nchains; hash->nodecount = 0; hash->maxcount = maxcount; hash->compare = compfun ? compfun : hash_comp_default; hash->function = hashfun ? hashfun : hash_fun_default; hash->dynamic = 0; /* 3 */ hash->mask = compute_mask(nchains); /* 4 */ clear_table(hash); /* 5 */ assert (hash_verify(hash)); return hash; } /* * Reset the hash scanner so that the next element retrieved by * hash_scan_next() shall be the first element on the first non-empty chain. * Notes: * 1. Locate the first non empty chain. * 2. If an empty chain is found, remember which one it is and set the next * pointer to refer to its first element. * 3. Otherwise if a chain is not found, set the next pointer to NULL * so that hash_scan_next() shall indicate failure. */ void hash_scan_begin(hscan_t *scan, hash_t *hash) { hash_val_t nchains = hash->nchains; hash_val_t chain; scan->table = hash; /* 1 */ for (chain = 0; chain < nchains && hash->table[chain] == 0; chain++) ; if (chain < nchains) { /* 2 */ scan->chain = chain; scan->next = hash->table[chain]; } else { /* 3 */ scan->next = NULL; } } /* * Retrieve the next node from the hash table, and update the pointer * for the next invocation of hash_scan_next(). * Notes: * 1. Remember the next pointer in a temporary value so that it can be * returned. * 2. This assertion essentially checks whether the module has been properly * initialized. The first point of interaction with the module should be * either hash_create() or hash_init(), both of which set hash_val_t_bit to * a non zero value. * 3. If the next pointer we are returning is not NULL, then the user is * allowed to call hash_scan_next() again. We prepare the new next pointer * for that call right now. That way the user is allowed to delete the node * we are about to return, since we will no longer be needing it to locate * the next node. * 4. If there is a next node in the chain (next->next), then that becomes the * new next node, otherwise ... * 5. We have exhausted the current chain, and must locate the next subsequent * non-empty chain in the table. * 6. If a non-empty chain is found, the first element of that chain becomes * the new next node. Otherwise there is no new next node and we set the * pointer to NULL so that the next time hash_scan_next() is called, a null * pointer shall be immediately returned. */ hnode_t *hash_scan_next(hscan_t *scan) { hnode_t *next = scan->next; /* 1 */ hash_t *hash = scan->table; hash_val_t chain = scan->chain + 1; hash_val_t nchains = hash->nchains; assert (hash_val_t_bit != 0); /* 2 */ if (next) { /* 3 */ if (next->next) { /* 4 */ scan->next = next->next; } else { while (chain < nchains && hash->table[chain] == 0) /* 5 */ chain++; if (chain < nchains) { /* 6 */ scan->chain = chain; scan->next = hash->table[chain]; } else { scan->next = NULL; } } } return next; } /* * Insert a node into the hash table. * Notes: * 1. It's illegal to insert more than the maximum number of nodes. The client * should verify that the hash table is not full before attempting an * insertion. * 2. The same key may not be inserted into a table twice. * 3. If the table is dynamic and the load factor is already at >= 2, * grow the table. * 4. We take the bottom N bits of the hash value to derive the chain index, * where N is the base 2 logarithm of the size of the hash table. */ void hash_insert(hash_t *hash, hnode_t *node, const void *key) { hash_val_t hkey, chain; assert (hash_val_t_bit != 0); assert (node->next == NULL); assert (hash->nodecount < hash->maxcount); /* 1 */ assert (hash_lookup(hash, key) == NULL); /* 2 */ if (hash->dynamic && hash->nodecount >= hash->highmark) /* 3 */ grow_table(hash); hkey = hash->function(key); chain = hkey & hash->mask; /* 4 */ node->key = key; node->hkey = hkey; node->next = hash->table[chain]; hash->table[chain] = node; hash->nodecount++; assert (hash_verify(hash)); } /* * Find a node in the hash table and return a pointer to it. * Notes: * 1. We hash the key and keep the entire hash value. As an optimization, when * we descend down the chain, we can compare hash values first and only if * hash values match do we perform a full key comparison. * 2. To locate the chain from among 2^N chains, we look at the lower N bits of * the hash value by anding them with the current mask. * 3. Looping through the chain, we compare the stored hash value inside each * node against our computed hash. If they match, then we do a full * comparison between the unhashed keys. If these match, we have located the * entry. */ hnode_t *hash_lookup(hash_t *hash, const void *key) { hash_val_t hkey, chain; hnode_t *nptr; hkey = hash->function(key); /* 1 */ chain = hkey & hash->mask; /* 2 */ for (nptr = hash->table[chain]; nptr; nptr = nptr->next) { /* 3 */ if (nptr->hkey == hkey && hash->compare(nptr->key, key) == 0) return nptr; } return NULL; } /* * Delete the given node from the hash table. Since the chains * are singly linked, we must locate the start of the node's chain * and traverse. * Notes: * 1. The node must belong to this hash table, and its key must not have * been tampered with. * 2. If this deletion will take the node count below the low mark, we * shrink the table now. * 3. Determine which chain the node belongs to, and fetch the pointer * to the first node in this chain. * 4. If the node being deleted is the first node in the chain, then * simply update the chain head pointer. * 5. Otherwise advance to the node's predecessor, and splice out * by updating the predecessor's next pointer. * 6. Indicate that the node is no longer in a hash table. */ hnode_t *tr_hash_delete(hash_t *hash, hnode_t *node) { hash_val_t chain; hnode_t *hptr; assert (hash_lookup(hash, node->key) == node); /* 1 */ assert (hash_val_t_bit != 0); if (hash->dynamic && hash->nodecount <= hash->lowmark && hash->nodecount > INIT_SIZE) shrink_table(hash); /* 2 */ chain = node->hkey & hash->mask; /* 3 */ hptr = hash->table[chain]; if (hptr == node) { /* 4 */ hash->table[chain] = node->next; } else { while (hptr->next != node) { /* 5 */ assert (hptr != 0); hptr = hptr->next; } assert (hptr->next == node); hptr->next = node->next; } hash->nodecount--; assert (hash_verify(hash)); node->next = NULL; /* 6 */ return node; } int hash_alloc_insert(hash_t *hash, const void *key, void *data) { hnode_t *node = hash->allocnode(hash->context); if (node) { hnode_init(node, data); hash_insert(hash, node, key); return 1; } return 0; } void hash_delete_free(hash_t *hash, hnode_t *node) { tr_hash_delete(hash, node); hash->freenode(node, hash->context); } /* * Exactly like hash_delete, except does not trigger table shrinkage. This is to be * used from within a hash table scan operation. See notes for hash_delete. */ hnode_t *hash_scan_delete(hash_t *hash, hnode_t *node) { hash_val_t chain; hnode_t *hptr; assert (hash_lookup(hash, node->key) == node); assert (hash_val_t_bit != 0); chain = node->hkey & hash->mask; hptr = hash->table[chain]; if (hptr == node) { hash->table[chain] = node->next; } else { while (hptr->next != node) hptr = hptr->next; hptr->next = node->next; } hash->nodecount--; assert (hash_verify(hash)); node->next = NULL; return node; } /* * Like hash_delete_free but based on hash_scan_delete. */ void hash_scan_delfree(hash_t *hash, hnode_t *node) { hash_scan_delete(hash, node); hash->freenode(node, hash->context); } /* * Verify whether the given object is a valid hash table. This means * Notes: * 1. If the hash table is dynamic, verify whether the high and * low expansion/shrinkage thresholds are powers of two. * 2. Count all nodes in the table, and test each hash value * to see whether it is correct for the node's chain. */ int hash_verify(hash_t *hash) { hashcount_t count = 0; hash_val_t chain; hnode_t *hptr; if (hash->dynamic) { /* 1 */ if (hash->lowmark >= hash->highmark) return 0; if (!is_power_of_two(hash->highmark)) return 0; if (!is_power_of_two(hash->lowmark)) return 0; } for (chain = 0; chain < hash->nchains; chain++) { /* 2 */ for (hptr = hash->table[chain]; hptr != 0; hptr = hptr->next) { if ((hptr->hkey & hash->mask) != chain) return 0; count++; } } if (count != hash->nodecount) return 0; return 1; } /* * Test whether the hash table is full and return 1 if this is true, * 0 if it is false. */ #undef hash_isfull int hash_isfull(hash_t *hash) { return hash->nodecount == hash->maxcount; } /* * Test whether the hash table is empty and return 1 if this is true, * 0 if it is false. */ #undef hash_isempty int hash_isempty(hash_t *hash) { return hash->nodecount == 0; } static hnode_t *hnode_alloc(void *context) { return malloc(sizeof *hnode_alloc(NULL)); } static void hnode_free(hnode_t *node, void *context) { free(node); } /* * Create a hash table node dynamically and assign it the given data. */ hnode_t *hnode_create(void *data) { hnode_t *node = malloc(sizeof *node); if (node) { node->data = data; node->next = NULL; } return node; } /* * Initialize a client-supplied node */ hnode_t *hnode_init(hnode_t *hnode, void *data) { hnode->data = data; hnode->next = NULL; return hnode; } /* * Destroy a dynamically allocated node. */ void hnode_destroy(hnode_t *hnode) { free(hnode); } #undef hnode_put void hnode_put(hnode_t *node, void *data) { node->data = data; } #undef hnode_get void *hnode_get(hnode_t *node) { return node->data; } #undef hnode_getkey const void *hnode_getkey(hnode_t *node) { return node->key; } #undef hash_count hashcount_t hash_count(hash_t *hash) { return hash->nodecount; } #undef hash_size hashcount_t hash_size(hash_t *hash) { return hash->nchains; } static hash_val_t hash_fun_default(const void *key) { static unsigned long randbox[] = { 0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U, 0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU, 0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU, 0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU, }; const unsigned char *str = key; hash_val_t acc = 0; while (*str) { acc ^= randbox[(*str + acc) & 0xf]; acc = (acc << 1) | (acc >> 31); acc &= 0xffffffffU; acc ^= randbox[((*str++ >> 4) + acc) & 0xf]; acc = (acc << 2) | (acc >> 30); acc &= 0xffffffffU; } return acc; } static int hash_comp_default(const void *key1, const void *key2) { return strcmp(key1, key2); } #ifdef KAZLIB_TEST_MAIN #include #include #include typedef char input_t[256]; static int tokenize(char *string, ...) { char **tokptr; va_list arglist; int tokcount = 0; va_start(arglist, string); tokptr = va_arg(arglist, char **); while (tokptr) { while (*string && isspace((unsigned char) *string)) string++; if (!*string) break; *tokptr = string; while (*string && !isspace((unsigned char) *string)) string++; tokptr = va_arg(arglist, char **); tokcount++; if (!*string) break; *string++ = 0; } va_end(arglist); return tokcount; } static char *dupstring(char *str) { int sz = strlen(str) + 1; char *new = malloc(sz); if (new) memcpy(new, str, sz); return new; } static hnode_t *new_node(void *c) { static hnode_t few[5]; static int count; if (count < 5) return few + count++; return NULL; } static void del_node(hnode_t *n, void *c) { } int main(void) { input_t in; hash_t *h = hash_create(HASHCOUNT_T_MAX, 0, 0); hnode_t *hn; hscan_t hs; char *tok1, *tok2, *val; const char *key; int prompt = 0; char *help = "a add value to hash table\n" "d delete value from hash table\n" "l lookup value in hash table\n" "n show size of hash table\n" "c show number of entries\n" "t dump whole hash table\n" "+ increase hash table (private func)\n" "- decrease hash table (private func)\n" "b print hash_t_bit value\n" "p turn prompt on\n" "s switch to non-functioning allocator\n" "q quit"; if (!h) puts("hash_create failed"); for (;;) { if (prompt) putchar('>'); fflush(stdout); if (!fgets(in, sizeof(input_t), stdin)) break; switch(in[0]) { case '?': puts(help); break; case 'b': printf("%d\n", hash_val_t_bit); break; case 'a': if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { puts("what?"); break; } key = dupstring(tok1); val = dupstring(tok2); if (!key || !val) { puts("out of memory"); free((void *) key); free(val); } if (!hash_alloc_insert(h, key, val)) { puts("hash_alloc_insert failed"); free((void *) key); free(val); break; } break; case 'd': if (tokenize(in+1, &tok1, (char **) 0) != 1) { puts("what?"); break; } hn = hash_lookup(h, tok1); if (!hn) { puts("hash_lookup failed"); break; } val = hnode_get(hn); key = hnode_getkey(hn); hash_scan_delfree(h, hn); free((void *) key); free(val); break; case 'l': if (tokenize(in+1, &tok1, (char **) 0) != 1) { puts("what?"); break; } hn = hash_lookup(h, tok1); if (!hn) { puts("hash_lookup failed"); break; } val = hnode_get(hn); puts(val); break; case 'n': printf("%lu\n", (unsigned long) hash_size(h)); break; case 'c': printf("%lu\n", (unsigned long) hash_count(h)); break; case 't': hash_scan_begin(&hs, h); while ((hn = hash_scan_next(&hs))) printf("%s\t%s\n", (char*) hnode_getkey(hn), (char*) hnode_get(hn)); break; case '+': grow_table(h); /* private function */ break; case '-': shrink_table(h); /* private function */ break; case 'q': exit(0); break; case '\0': break; case 'p': prompt = 1; break; case 's': hash_set_allocator(h, new_node, del_node, NULL); break; default: putchar('?'); putchar('\n'); break; } } return 0; } #endif openvpn-auth-ldap-auth-ldap-2.0.4/src/hash.h000066400000000000000000000220261332642612100206210ustar00rootroot00000000000000/* * Hash Table Data Type vi:ts=4:sw=4:expandtab: * Copyright (C) 1997 Kaz Kylheku * * Free Software License: * * All rights are reserved by the author, with the following exceptions: * Permission is granted to freely reproduce and distribute this software, * possibly in exchange for a fee, provided that this copyright notice appears * intact. Permission is also granted to adapt this software to produce * derivative works, as long as the modified versions carry this copyright * notice and additional notices stating that the work has been modified. * This source code may be translated into executable form and incorporated * into proprietary software; there is no requirement for such software to * contain a copyright notice related to this source. * * $Id: hash.h,v 1.22.2.7 2000/11/13 01:36:45 kaz Exp $ * $Name: kazlib_1_20 $ */ #ifndef HASH_H #define HASH_H #include #ifdef KAZLIB_SIDEEFFECT_DEBUG #include "sfx.h" #endif /* * Blurb for inclusion into C++ translation units */ #ifdef __cplusplus extern "C" { #endif typedef unsigned long hashcount_t; #define HASHCOUNT_T_MAX ULONG_MAX typedef unsigned long hash_val_t; #define HASH_VAL_T_MAX ULONG_MAX /* * Hash chain node structure. * Notes: * 1. This preprocessing directive is for debugging purposes. The effect is * that if the preprocessor symbol KAZLIB_OPAQUE_DEBUG is defined prior to the * inclusion of this header, then the structure shall be declared as having * the single member int __OPAQUE__. This way, any attempts by the * client code to violate the principles of information hiding (by accessing * the structure directly) can be diagnosed at translation time. However, * note the resulting compiled unit is not suitable for linking. * 2. This is a pointer to the next node in the chain. In the last node of a * chain, this pointer is null. * 3. The key is a pointer to some user supplied data that contains a unique * identifier for each hash node in a given table. The interpretation of * the data is up to the user. When creating or initializing a hash table, * the user must supply a pointer to a function for comparing two keys, * and a pointer to a function for hashing a key into a numeric value. * 4. The value is a user-supplied pointer to void which may refer to * any data object. It is not interpreted in any way by the hashing * module. * 5. The hashed key is stored in each node so that we don't have to rehash * each key when the table must grow or shrink. */ typedef struct hnode_t { #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) /* 1 */ struct hnode_t *hash_next; /* 2 */ const void *hash_key; /* 3 */ void *hash_data; /* 4 */ hash_val_t hash_hkey; /* 5 */ #else int hash_dummy; #endif } hnode_t; /* * The comparison function pointer type. A comparison function takes two keys * and produces a value of -1 if the left key is less than the right key, a * value of 0 if the keys are equal, and a value of 1 if the left key is * greater than the right key. */ typedef int (*hash_comp_t)(const void *, const void *); /* * The hashing function performs some computation on a key and produces an * integral value of type hash_val_t based on that key. For best results, the * function should have a good randomness properties in *all* significant bits * over the set of keys that are being inserted into a given hash table. In * particular, the most significant bits of hash_val_t are most significant to * the hash module. Only as the hash table expands are less significant bits * examined. Thus a function that has good distribution in its upper bits but * not lower is preferrable to one that has poor distribution in the upper bits * but not the lower ones. */ typedef hash_val_t (*hash_fun_t)(const void *); /* * allocator functions */ typedef hnode_t *(*hnode_alloc_t)(void *); typedef void (*hnode_free_t)(hnode_t *, void *); /* * This is the hash table control structure. It keeps track of information * about a hash table, as well as the hash table itself. * Notes: * 1. Pointer to the hash table proper. The table is an array of pointers to * hash nodes (of type hnode_t). If the table is empty, every element of * this table is a null pointer. A non-null entry points to the first * element of a chain of nodes. * 2. This member keeps track of the size of the hash table---that is, the * number of chain pointers. * 3. The count member maintains the number of elements that are presently * in the hash table. * 4. The maximum count is the greatest number of nodes that can populate this * table. If the table contains this many nodes, no more can be inserted, * and the hash_isfull() function returns true. * 5. The high mark is a population threshold, measured as a number of nodes, * which, if exceeded, will trigger a table expansion. Only dynamic hash * tables are subject to this expansion. * 6. The low mark is a minimum population threshold, measured as a number of * nodes. If the table population drops below this value, a table shrinkage * will occur. Only dynamic tables are subject to this reduction. No table * will shrink beneath a certain absolute minimum number of nodes. * 7. This is the a pointer to the hash table's comparison function. The * function is set once at initialization or creation time. * 8. Pointer to the table's hashing function, set once at creation or * initialization time. * 9. The current hash table mask. If the size of the hash table is 2^N, * this value has its low N bits set to 1, and the others clear. It is used * to select bits from the result of the hashing function to compute an * index into the table. * 10. A flag which indicates whether the table is to be dynamically resized. It * is set to 1 in dynamically allocated tables, 0 in tables that are * statically allocated. */ typedef struct hash_t { #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) struct hnode_t **hash_table; /* 1 */ hashcount_t hash_nchains; /* 2 */ hashcount_t hash_nodecount; /* 3 */ hashcount_t hash_maxcount; /* 4 */ hashcount_t hash_highmark; /* 5 */ hashcount_t hash_lowmark; /* 6 */ hash_comp_t hash_compare; /* 7 */ hash_fun_t hash_function; /* 8 */ hnode_alloc_t hash_allocnode; hnode_free_t hash_freenode; void *hash_context; hash_val_t hash_mask; /* 9 */ int hash_dynamic; /* 10 */ #else int hash_dummy; #endif } hash_t; /* * Hash scanner structure, used for traversals of the data structure. * Notes: * 1. Pointer to the hash table that is being traversed. * 2. Reference to the current chain in the table being traversed (the chain * that contains the next node that shall be retrieved). * 3. Pointer to the node that will be retrieved by the subsequent call to * hash_scan_next(). */ typedef struct hscan_t { #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) hash_t *hash_table; /* 1 */ hash_val_t hash_chain; /* 2 */ hnode_t *hash_next; /* 3 */ #else int hash_dummy; #endif } hscan_t; extern hash_t *hash_create(hashcount_t, hash_comp_t, hash_fun_t); extern void hash_set_allocator(hash_t *, hnode_alloc_t, hnode_free_t, void *); extern void hash_destroy(hash_t *); extern void hash_free_nodes(hash_t *); extern void hash_free(hash_t *); extern hash_t *hash_init(hash_t *, hashcount_t, hash_comp_t, hash_fun_t, hnode_t **, hashcount_t); extern void hash_insert(hash_t *, hnode_t *, const void *); extern hnode_t *hash_lookup(hash_t *, const void *); /* Avoid symbol conflict with stupidly named function in the GNU Objective-C runtime */ extern hnode_t *tr_hash_delete(hash_t *, hnode_t *); extern int hash_alloc_insert(hash_t *, const void *, void *); extern void hash_delete_free(hash_t *, hnode_t *); extern void hnode_put(hnode_t *, void *); extern void *hnode_get(hnode_t *); extern const void *hnode_getkey(hnode_t *); extern hashcount_t hash_count(hash_t *); extern hashcount_t hash_size(hash_t *); extern int hash_isfull(hash_t *); extern int hash_isempty(hash_t *); extern void hash_scan_begin(hscan_t *, hash_t *); extern hnode_t *hash_scan_next(hscan_t *); extern hnode_t *hash_scan_delete(hash_t *, hnode_t *); extern void hash_scan_delfree(hash_t *, hnode_t *); extern int hash_verify(hash_t *); extern hnode_t *hnode_create(void *); extern hnode_t *hnode_init(hnode_t *, void *); extern void hnode_destroy(hnode_t *); #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) #ifdef KAZLIB_SIDEEFFECT_DEBUG #define hash_isfull(H) (SFX_CHECK(H)->hash_nodecount == (H)->hash_maxcount) #else #define hash_isfull(H) ((H)->hash_nodecount == (H)->hash_maxcount) #endif #define hash_isempty(H) ((H)->hash_nodecount == 0) #define hash_count(H) ((H)->hash_nodecount) #define hash_size(H) ((H)->hash_nchains) #define hnode_get(N) ((N)->hash_data) #define hnode_getkey(N) ((N)->hash_key) #define hnode_put(N, V) ((N)->hash_data = (V)) #endif #ifdef __cplusplus } #endif #endif openvpn-auth-ldap-auth-ldap-2.0.4/src/openvpn-cr.c000066400000000000000000000035711332642612100217640ustar00rootroot00000000000000#include "openvpn-cr.h" #include "base64.h" #include static const char * static_cr_label = "SCRV1"; static const char * dynamic_cr_label = "CRV1"; int set_token_b64(const char * source, char * destination) { if (Base64decode_len(source) >= MAXTOKENLENGTH) return 0; Base64decode(destination, source); return 1; } int set_token(const char * source, char * destination) { if (strlen(source) >= MAXTOKENLENGTH) return 0; strncpy(destination, source, MAXTOKENLENGTH); return 1; } int extract_openvpn_cr(const char *response, openvpn_response *result, char **error_message) { const char *tokenIndexes[15]; tokenIndexes[0] = response; int tokenCnt = 1; const char *p; for (p = response; *p; ++p) { if (*p == ':') tokenIndexes[tokenCnt++] = p + 1; } if (tokenCnt == 3 && strstr(response, static_cr_label) == response) { if (!set_token(static_cr_label, result->protocol)){ *error_message = "Unable to set static protocol information."; return 0; } if (!set_token_b64(tokenIndexes[1], result->password)) { *error_message = "Unable to extract password from static cr."; return 0; } if (!set_token_b64(tokenIndexes[2], result->response)) { *error_message = "Unable to extract response from static cr."; return 0; } } else if (tokenCnt == 5 && strstr(response, dynamic_cr_label) == response) { if (!set_token(dynamic_cr_label, result->protocol)) { *error_message = "Unable to set dynamic protocol information."; return 0; } if (!set_token_b64(tokenIndexes[2], result->password)) { *error_message = "Unable to extract password from dynamic cr."; return 0; } if (!set_token_b64(tokenIndexes[4], result->response)) { *error_message = "Unable to extract response from dynamic cr."; return 0; } } else { *error_message = "Incorrectly formatted cr string."; return 0; } return 1; } openvpn-auth-ldap-auth-ldap-2.0.4/src/openvpn-cr.h000066400000000000000000000010401332642612100217560ustar00rootroot00000000000000#ifndef OPENVPN_CR_H #define OPENVPN_CR_H #define MAXTOKENLENGTH 1024 typedef struct { char protocol[6]; char password[MAXTOKENLENGTH]; char response[MAXTOKENLENGTH]; } openvpn_response; /* Parse a string containing an openvpn response and store the result into an openvpn_response struct. If parsing succeeds result will be in result and 1 is returned. If parsing fails, 0 is returned, error_message is set */ int extract_openvpn_cr(const char *response, openvpn_response *result, char **error_message); #endifopenvpn-auth-ldap-auth-ldap-2.0.4/src/strlcpy.c000066400000000000000000000045311332642612100213720ustar00rootroot00000000000000/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #ifndef HAVE_STRLCPY #include #include /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(dst, src, siz) char *dst; const char *src; size_t siz; { char *d = dst; const char *s = src; size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } #endif /* HAVE_STRLCPY */ openvpn-auth-ldap-auth-ldap-2.0.4/src/strlcpy.h000066400000000000000000000031461332642612100214000ustar00rootroot00000000000000/* * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include #endif #ifndef HAVE_STRLCPY size_t strlcpy(char *dst, const char *src, size_t siz); #endif /* HAVE_STRLCPY */ openvpn-auth-ldap-auth-ldap-2.0.4/src/testplugin.c000066400000000000000000000144551332642612100220760ustar00rootroot00000000000000/* * testplugin.c vi:ts=4:sw=4:expandtab: * OpenVPN LDAP Authentication Plugin Test Driver * * Copyright (c) 2005 - 2007 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include /* Argument / environment templates */ const char username_template[] = "username="; const char password_template[] = "password="; const char conf_template[] = "/tmp/openvpn-auth-ldap-test.XXXXXXXXXXXXX"; /* Configuration data */ typedef struct { /* User name and password environmental variables */ char *username; char *password; /* Path to config file */ const char *config_file; /* OpenVPN plugin environment */ const char **envp; /* OpenVPN plugin open/close arguments */ const char **argp; /* OpenVPN 'command line' script arguments */ const char **argp_script; } plugin_data; /** * Initialize the plugin data structure. This function is not thread-safe; it * interacts with the user on stdin, and calls other non-reentrant functions (eg getpass()). */ static plugin_data *plugin_data_init (const char *config_file) { plugin_data *data; char username[128]; char *password; /* Alloc and zero-initialize a new data structure */ data = calloc(1, sizeof(plugin_data)); /* Fetch the username and password */ printf("Username: "); if (fgets(username, sizeof(username), stdin) == NULL) { errx(1, "Failed to read username"); } password = getpass("Password: "); /* Strip off the trailing \n */ username[strlen(username) - 1] = '\0'; /* Assemble the username env variable */ data->username = malloc(sizeof(username_template) + strlen(username)); strcpy(data->username, username_template); strcat(data->username, username); /* Assemble the password env variable */ data->password = malloc(sizeof(password_template) + strlen(password)); strcpy(data->password, password_template); strcat(data->password, password); /* Set up the plugin environment array -- username, password, ifconfig_pool_remote_ip, NULL */ data->envp = calloc(4, sizeof(char *)); data->envp[0] = data->username; data->envp[1] = data->password; data->envp[2] = "ifconfig_pool_remote_ip=10.0.50.1"; data->envp[3] = NULL; /* Set up the plugin argument array -- plugin path, config file, NULL */ data->argp = calloc(3, sizeof(char *)); data->argp[0] = "plugin.so"; data->argp[1] = config_file; data->argp[2] = NULL; /* Set up the plugin "script" argument array -- plugin path, dynamic config file, NULL */ // TODO: wire up dynamic config file support. data->argp_script = calloc(3, sizeof(char *)); data->argp_script[0] = "plugin.so"; data->argp_script[1] = NULL; data->argp_script[2] = NULL; return data; } static void plugin_data_free (plugin_data *data) { if (data->username) free(data->username); if (data->password) free(data->password); if (data->envp) free(data->envp); if (data->argp) free(data->argp); if (data->argp_script) free(data->argp_script); free(data); } int main(int argc, const char *argv[]) { openvpn_plugin_handle_t handle; plugin_data *data; const char *config_file; unsigned int plugin_type; int retval = 1; int err; if (argc != 2) { errx(1, "Usage: %s ", argv[0]); } else { config_file = argv[1]; } /* Configure the plugin environment */ data = plugin_data_init(config_file); handle = openvpn_plugin_open_v1(&plugin_type, data->argp, data->envp); if (!handle) { printf("Initialization Failed!\n"); goto cleanup; } /* Authenticate */ err = openvpn_plugin_func_v1(handle, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY, data->argp_script, data->envp); if (err != OPENVPN_PLUGIN_FUNC_SUCCESS) { printf("Authorization Failed!\n"); goto cleanup; } else { printf("Authorization Succeed!\n"); } /* Client Connect */ err = openvpn_plugin_func_v1(handle, OPENVPN_PLUGIN_CLIENT_CONNECT, data->argp_script, data->envp); if (err != OPENVPN_PLUGIN_FUNC_SUCCESS) { printf("client-connect failed!\n"); goto cleanup; } else { printf("client-connect succeed!\n"); } /* Client Disconnect */ err = openvpn_plugin_func_v1(handle, OPENVPN_PLUGIN_CLIENT_DISCONNECT, data->argp, data->envp); if (err != OPENVPN_PLUGIN_FUNC_SUCCESS) { printf("client-disconnect failed!\n"); goto cleanup; } else { printf("client-disconnect succeed!\n"); } /* Everything worked. Set our return value accordingly. */ retval = 0; cleanup: openvpn_plugin_close_v1(handle); plugin_data_free(data); exit(retval); } openvpn-auth-ldap-auth-ldap-2.0.4/src/xmalloc.c000066400000000000000000000044151332642612100213320ustar00rootroot00000000000000/* * xmalloc.c vi:ts=4:sw=4:expandtab: * "Safe" malloc routines -- and by safe, I mean: "fail quickly" * * Copyright (c) 2005 - 2007 Landon Fuller * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include /* Safe Malloc */ void *xmalloc(size_t size) { void *ptr; ptr = malloc(size); if (!ptr) err(1, "malloc returned NULL"); return (ptr); } void *xrealloc(void *oldptr, size_t size) { void *ptr; ptr = realloc(oldptr, size); if (!ptr) err(1, "realloc returned NULL"); oldptr = ptr; return (ptr); } char *xstrdup(const char *str) { void *ptr; ptr = strdup(str); if (!ptr) err(1, "strdup returned NULL"); return (ptr); } openvpn-auth-ldap-auth-ldap-2.0.4/src/xmalloc.h000066400000000000000000000036211332642612100213350ustar00rootroot00000000000000/* * xmalloc.h vi:ts=4:sw=4:expandtab: * * "Safe" malloc routines -- and by safe, I mean "fail quickly" * * Copyright (c) 2006 Three Rings Design, Inc. * Copyright (c) 2005 - 2006 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef MALLOC_H #define MALLOC_H #include void *xmalloc(size_t size); void *xrealloc(void *ptr, size_t size); char *xstrdup(const char *str); #endif /* MALLOC_H */ openvpn-auth-ldap-auth-ldap-2.0.4/tests/000077500000000000000000000000001332642612100200765ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/tests/Makefile.in000077500000000000000000000026231332642612100221510ustar00rootroot00000000000000srcdir= @srcdir@ top_srcdir= @top_srcdir@ top_builddir= @top_builddir@ VPATH= @srcdir@ include ${top_builddir}/Mk/autoconf.mk include ${top_builddir}/Mk/compile.mk include ${top_builddir}/Mk/subdir.mk TEST_OBJS= tests.o \ PXTestAssert.o \ PXTestCase.o \ PXTestCaseRunner.o \ PXTestConsoleResultHandler.o \ PXTestException.o \ TRArrayTests.o \ TRAuthLDAPConfigTests.o \ TRAutoreleasePoolTests.o \ TRConfigLexerTests.o \ TRConfigTests.o \ TRConfigTokenTests.o \ TRHashTests.o \ TRLDAPAccountRepositoryTests.o \ TRLDAPConnectionTests.o \ TRLDAPEntryTests.o \ TRLDAPGroupConfigTests.o \ TRLDAPSearchFilterTests.o \ TRLocalPacketFilterTests.o \ TRObjectTests.o \ mockpf.o \ TRPFAddressTests.o \ TRStringTests.o \ TRVPNSessionTests.o CFLAGS+= -DTEST_DATA=\"${srcdir}/data\" OBJCFLAGS+= -DTEST_DATA=\"${srcdir}/data\" LIBS+= -L${top_builddir}/src -lauth-ldap \ $(OBJC_LIBS) $(LDAP_LIBS) LDFLAGS+= $(LIBS) # File Substitutions EDIT= sed \ -e 's,@TEST_DATA\@,$(srcdir)/data,g' # Recompile the tests every time all:: tests # Generate any headers before subdirs are traversed pre-all:: # Generated File(s) tests.h: tests.h.in $(EDIT) $(srcdir)/tests.h.in > $@ tests: ${TEST_OBJS} ../src/libauth-ldap.a ${CC} -o $@ ${TEST_OBJS} ${LDFLAGS} test:: tests ./tests install:: clean:: rm -f $(TEST_OBJS) tests distclean:: clean rm -f Makefile openvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestAssert.h000066400000000000000000001343111332642612100226230ustar00rootroot00000000000000 // // Test macros compatible with (and borrowed from) SenTestCase // Derived from GTMSenTestCase.h // // Copyright 2007-2008 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. // // Portions of this file fall under the following licenses // // Copyright 2012 Landon Fuller // Copyright (c) 1997-2005, Sen:te (Sente SA). All rights reserved. // // Use of this source code is governed by the following license: // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // (1) Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // (2) Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. // IN NO EVENT SHALL Sente SA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Note: this license is equivalent to the FreeBSD license. // // This notice may not be removed from this file. // Some extra test case macros that would have been convenient for SenTestingKit // to provide. I didn't stick GTM in front of the Macro names, so that they would // be easy to remember. #import #import "PXTestException.h" /* libcheck-compatible assertions */ #define fail_unless(expr, ...) STAssertTrue(expr, "Legacy assertion '"#expr"' failed" , ## __VA_ARGS__) #define fail_if(expr, ...) STAssertFalse(expr, "Legacy assertion '"#expr"' failed" , ## __VA_ARGS__) #ifdef __cplusplus extern "C" { #endif TRString *STComposeString(const char *, ...); #ifdef __cplusplus } #endif // Generates a failure when a1 != noErr // Args: // a1: should be either an OSErr or an OSStatus // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertNoErr(a1, description, ...) \ do { \ @try { \ OSStatus a1value = (a1); \ if (a1value != noErr) { \ TRString *_expression = [TRString stringWithFormat:"Expected noErr, got %ld for (%s)", a1value, #a1]; \ [self failWithException:([PXTestException failureInCondition:_expression \ isTrue:NO \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:"%", STComposeString(description, ##__VA_ARGS__)])]; \ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat:"(%s) == noErr fails", #a1] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) // Generates a failure when a1 != a2 // Args: // a1: received value. Should be either an OSErr or an OSStatus // a2: expected value. Should be either an OSErr or an OSStatus // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertErr(a1, a2, description, ...) \ do { \ @try { \ OSStatus a1value = (a1); \ OSStatus a2value = (a2); \ if (a1value != a2value) { \ TRString *_expression = [TRString stringWithFormat:"Expected %s(%ld) but got %ld for (%s)", #a2, a2value, a1value, #a1]; \ [self failWithException:([PXTestException failureInCondition:_expression \ isTrue:NO \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:"%", STComposeString(description, ##__VA_ARGS__)])]; \ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat:"(%s) == (%s) fails", #a1, #a2] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) // Generates a failure when a1 is NULL // Args: // a1: should be a pointer (use STAssertNotNil for an object) // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertNotNULL(a1, description, ...) \ do { \ @try { \ const void* a1value = (a1); \ if (a1value == NULL) { \ TRString *_expression = [TRString stringWithFormat:"((%s) != NULL)", #a1]; \ [self failWithException:([PXTestException failureInCondition:_expression \ isTrue:NO \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:"%", STComposeString(description, ##__VA_ARGS__)])]; \ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat:"(%s) != NULL fails", #a1] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) // Generates a failure when a1 is not NULL // Args: // a1: should be a pointer (use STAssertNil for an object) // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertNULL(a1, description, ...) \ do { \ @try { \ const void* a1value = (a1); \ if (a1value != NULL) { \ TRString *_expression = [TRString stringWithFormat:"((%s) == NULL)", #a1]; \ [self failWithException:([PXTestException failureInCondition:_expression \ isTrue:NO \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:"%", STComposeString(description, ##__VA_ARGS__)])]; \ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat:"(%s) == NULL fails", #a1] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) // Generates a failure when a1 is equal to a2. This test is for C scalars, // structs and unions. // Args: // a1: argument 1 // a2: argument 2 // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertNotEquals(a1, a2, description, ...) \ do { \ @try { \ if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ [self failWithException:[PXTestException failureInFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:[TRString stringWithFormat: "Type mismatch -- %s", [STComposeString(description, ##__VA_ARGS__) cString]]]]; \ } else { \ __typeof__(a1) a1value = (a1); \ __typeof__(a2) a2value = (a2); \ if (a1value == a2value) { \ TRString *_expression = [TRString stringWithFormat:"((%s) != (%s))", #a1, #a2]; \ [self failWithException:([PXTestException failureInCondition:_expression \ isTrue:NO \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:"%s", STComposeString(description, ##__VA_ARGS__)])]; \ }\ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat:"(%s) != (%s)", #a1, #a2] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) // Generates a failure when a1 is equal to a2. This test is for objects. // Args: // a1: argument 1. object. // a2: argument 2. object. // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertNotEqualObjects(a1, a2, description, ...) \ do { \ @try {\ id a1value = (a1); \ id a2value = (a2); \ if ( (strcmp(@encode(__typeof__(a1value)), @encode(id)) == 0) && \ (strcmp(@encode(__typeof__(a2value)), @encode(id)) == 0) && \ (![(id)a1value isEqual:(id)a2value]) ) continue; \ [self failWithException:([PXTestException failureInEqualityBetweenObject:a1value \ andObject:a2value \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:"%", STComposeString(description, ##__VA_ARGS__)])]; \ }\ @catch (id anException) {\ [self failWithException:([PXTestException failureInRaise:[TRString stringWithFormat:"(%s) != (%s)", #a1, #a2] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:"%", STComposeString(description, ##__VA_ARGS__)])]; \ }\ } while(0) // Generates a failure when a1 is not 'op' to a2. This test is for C scalars. // Args: // a1: argument 1 // a2: argument 2 // op: operation // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertOperation(a1, a2, op, description, ...) \ do { \ @try { \ if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ [self failWithException:[PXTestException failureInFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:[TRString stringWithFormat: "Type mismatch -- %s", [STComposeString(description, ##__VA_ARGS__) cString]]]]; \ } else { \ __typeof__(a1) a1value = (a1); \ __typeof__(a2) a2value = (a2); \ if (!(a1value op a2value)) { \ double a1DoubleValue = a1value; \ double a2DoubleValue = a2value; \ TRString *_expression = [TRString stringWithFormat:"(%s (%lg) %s %s (%lg))", #a1, a1DoubleValue, #op, #a2, a2DoubleValue]; \ [self failWithException:([PXTestException failureInCondition:_expression \ isTrue:NO \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:"%", STComposeString(description, ##__VA_ARGS__)])]; \ } \ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException \ failureInRaise:[TRString stringWithFormat:"(%s) %s (%s)", #a1, #op, #a2] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) // Generates a failure when a1 is not > a2. This test is for C scalars. // Args: // a1: argument 1 // a2: argument 2 // op: operation // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertGreaterThan(a1, a2, description, ...) \ STAssertOperation(a1, a2, >, description, ##__VA_ARGS__) // Generates a failure when a1 is not >= a2. This test is for C scalars. // Args: // a1: argument 1 // a2: argument 2 // op: operation // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertGreaterThanOrEqual(a1, a2, description, ...) \ STAssertOperation(a1, a2, >=, description, ##__VA_ARGS__) // Generates a failure when a1 is not < a2. This test is for C scalars. // Args: // a1: argument 1 // a2: argument 2 // op: operation // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertLessThan(a1, a2, description, ...) \ STAssertOperation(a1, a2, <, description, ##__VA_ARGS__) // Generates a failure when a1 is not <= a2. This test is for C scalars. // Args: // a1: argument 1 // a2: argument 2 // op: operation // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertLessThanOrEqual(a1, a2, description, ...) \ STAssertOperation(a1, a2, <=, description, ##__VA_ARGS__) // Generates a failure when string a1 is not equal to string a2. This call // differs from STAssertEqualObjects in that strings that are different in // composition (precomposed vs decomposed) will compare equal if their final // representation is equal. // ex O + umlaut decomposed is the same as O + umlaut composed. // Args: // a1: string 1 // a2: string 2 // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertEqualStrings(a1, a2, description, ...) \ do { \ @try { \ id a1value = (a1); \ id a2value = (a2); \ if (a1value == a2value) continue; \ if ([a1value isKindOfClass:[TRString class]] && \ [a2value isKindOfClass:[TRString class]] && \ [a1value compare:a2value options:0] == NSOrderedSame) continue; \ [self failWithException:[PXTestException failureInEqualityBetweenObject: a1value \ andObject: a2value \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat: "(%s) == (%s)", #a1, #a2] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) // Generates a failure when string a1 is equal to string a2. This call // differs from STAssertEqualObjects in that strings that are different in // composition (precomposed vs decomposed) will compare equal if their final // representation is equal. // ex O + umlaut decomposed is the same as O + umlaut composed. // Args: // a1: string 1 // a2: string 2 // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertNotEqualStrings(a1, a2, description, ...) \ do { \ @try { \ id a1value = (a1); \ id a2value = (a2); \ if ([a1value isKindOfClass:[TRString class]] && \ [a2value isKindOfClass:[TRString class]] && \ [a1value compare:a2value options:0] != NSOrderedSame) continue; \ [self failWithException:[PXTestException failureInEqualityBetweenObject: a1value \ andObject: a2value \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat: "(%s) != (%s)", #a1, #a2] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) // Generates a failure when c-string a1 is not equal to c-string a2. // Args: // a1: string 1 // a2: string 2 // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertEqualCStrings(a1, a2, description, ...) \ do { \ @try { \ const char* a1value = (a1); \ const char* a2value = (a2); \ if (a1value == a2value) continue; \ if (strcmp(a1value, a2value) == 0) continue; \ [self failWithException:[PXTestException failureInEqualityBetweenObject: [TRString stringWithCString:a1value] \ andObject: [TRString stringWithCString:a2value] \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat: "(%s) == (%s)", #a1, #a2] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) // Generates a failure when c-string a1 is equal to c-string a2. // Args: // a1: string 1 // a2: string 2 // description: A format string as in the printf() function. Can be nil or // an empty string but must be present. // ...: A variable number of arguments to the format string. Can be absent. #define STAssertNotEqualCStrings(a1, a2, description, ...) \ do { \ @try { \ const char* a1value = (a1); \ const char* a2value = (a2); \ if (strcmp(a1value, a2value) != 0) continue; \ [self failWithException:[PXTestException failureInEqualityBetweenObject: [TRString stringWithCString:a1value] \ andObject: [TRString stringWithCString:a2value] \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat: "(%s) != (%s)", #a1, #a2] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) // SENTE_BEGIN /*" Generates a failure when !{ [a1 isEqualTo:a2] } is false (or one is nil and the other is not). _{a1 The object on the left.} _{a2 The object on the right.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertEqualObjects(a1, a2, description, ...) \ do { \ @try { \ id a1value = (a1); \ id a2value = (a2); \ if (a1value == a2value) continue; \ if ((strcmp(@encode(__typeof__(a1value)), @encode(id)) == 0) && \ (strcmp(@encode(__typeof__(a2value)), @encode(id)) == 0) && \ [(id)a1value isEqual: (id)a2value]) continue; \ [self failWithException:[PXTestException failureInEqualityBetweenObject: a1value \ andObject: a2value \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat: "(%s) == (%s)", #a1, #a2] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) /*" Generates a failure when a1 is not equal to a2. This test is for C scalars, structs and unions. _{a1 The argument on the left.} _{a2 The argument on the right.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertEquals(a1, a2, description, ...) \ do { \ @try { \ if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ [self failWithException:[PXTestException failureInFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:[TRString stringWithFormat: "Type mismatch -- %s", [STComposeString(description, ##__VA_ARGS__) cString]]]]; \ } else { \ __typeof__(a1) a1value = (a1); \ __typeof__(a2) a2value = (a2); \ if (a1value != a2value) { \ [self failWithException:[PXTestException failureInEqualityBetweenValue: [TRString stringWithCString: #a1] \ andValue: [TRString stringWithCString: #a2] \ withAccuracy: nil \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat: "(%s) == (%s)", #a1, #a2] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) #define STAbsoluteDifference(left,right) (MAX(left,right)-MIN(left,right)) /*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false. This test is for scalars such as floats and doubles where small differences could make these items not exactly equal, but also works for all scalars. _{a1 The scalar on the left.} _{a2 The scalar on the right.} _{accuracy The maximum difference between a1 and a2 for these values to be considered equal.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertEqualsWithAccuracy(a1, a2, accuracy, description, ...) \ do { \ @try { \ if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \ [self failWithException:[PXTestException failureInFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:[TRString stringWithFormat: "Type mismatch -- %s", [STComposeString(description, ##__VA_ARGS__) cString]]]]; \ } else { \ __typeof__(a1) a1value = (a1); \ __typeof__(a2) a2value = (a2); \ __typeof__(accuracy) accuracyvalue = (accuracy); \ if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \ NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ NSValue *accuracyencoded = [NSValue value:&accuracyvalue withObjCType:@encode(__typeof__(accuracy))]; \ [self failWithException:[PXTestException failureInEqualityBetweenValue: a1encoded \ andValue: a2encoded \ withAccuracy: accuracyencoded \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat: "(%s) == (%s)", #a1, #a2] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) /*" Generates a failure unconditionally. _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STFail(description, ...) \ [self failWithException:[PXTestException failureInFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]] /*" Generates a failure when a1 is not nil. _{a1 An object.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertNil(a1, description, ...) \ do { \ @try { \ id a1value = (a1); \ if (a1value != nil) { \ TRString *_a1 = [TRString stringWithCString: #a1]; \ TRString *_expression = [TRString stringWithFormat:"((%p) == nil)", _a1]; \ [self failWithException:[PXTestException failureInCondition: _expression \ isTrue: NO \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat: "(%s) == nil fails", #a1] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) /*" Generates a failure when a1 is nil. _{a1 An object.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertNotNil(a1, description, ...) \ do { \ @try { \ id a1value = (a1); \ if (a1value == nil) { \ TRString *_a1 = [TRString stringWithCString: #a1]; \ TRString *_expression = [TRString stringWithFormat:"((%p) != nil)", _a1]; \ [self failWithException:[PXTestException failureInCondition: _expression \ isTrue: NO \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat: "(%s) != nil fails", #a1] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while(0) /*" Generates a failure when expression evaluates to false. _{expr The expression that is tested.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertTrue(expr, description, ...) \ do { \ BOOL _evaluatedExpression = (expr); \ if (!_evaluatedExpression) { \ TRString *_expression = [TRString stringWithCString: #expr]; \ [self failWithException:[PXTestException failureInCondition: _expression \ isTrue: NO \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while (0) /*" Generates a failure when expression evaluates to false and in addition will generate error messages if an exception is encountered. _{expr The expression that is tested.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertTrueNoThrow(expr, description, ...) \ do { \ @try { \ BOOL _evaluatedExpression = (expr); \ if (!_evaluatedExpression) { \ TRString *_expression = [TRString stringWithCString: #expr]; \ [self failWithException:[PXTestException failureInCondition: _expression \ isTrue: NO \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat: "(%s) ", #expr] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while (0) /*" Generates a failure when the expression evaluates to true. _{expr The expression that is tested.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertFalse(expr, description, ...) \ do { \ BOOL _evaluatedExpression = (expr); \ if (_evaluatedExpression) { \ TRString *_expression = [TRString stringWithCString: #expr]; \ [self failWithException:[PXTestException failureInCondition: _expression \ isTrue: YES \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while (0) /*" Generates a failure when the expression evaluates to true and in addition will generate error messages if an exception is encountered. _{expr The expression that is tested.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertFalseNoThrow(expr, description, ...) \ do { \ @try { \ BOOL _evaluatedExpression = (expr); \ if (_evaluatedExpression) { \ TRString *_expression = [TRString stringWithCString: #expr]; \ [self failWithException:[PXTestException failureInCondition: _expression \ isTrue: YES \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise:[TRString stringWithFormat: "!(%s) ", #expr] \ exception:anException \ inFile:[TRString stringWithCString:__FILE__] \ atLine:__LINE__ \ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while (0) /*" Generates a failure when expression does not throw an exception. _{expression The expression that is evaluated.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent. "*/ #define STAssertThrows(expr, description, ...) \ do { \ @try { \ (expr); \ } \ @catch (id anException) { \ continue; \ } \ [self failWithException:[PXTestException failureInRaise: [TRString stringWithCString:#expr] \ exception: nil \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } while (0) /*" Generates a failure when expression does not throw an exception of a specific class. _{expression The expression that is evaluated.} _{specificException The specified class of the exception.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertThrowsSpecific(expr, specificException, description, ...) \ do { \ @try { \ (expr); \ } \ @catch (specificException *anException) { \ continue; \ } \ @catch (id anException) { \ TRString *_descrip = STComposeString("(Expected exception: %@) %", TRStringFromClass([specificException class]), description); \ [self failWithException:[PXTestException failureInRaise: [TRString stringWithCString:#expr] \ exception: anException \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ continue; \ } \ TRString *_descrip = STComposeString("(Expected exception: %@) %", TRStringFromClass([specificException class]), description); \ [self failWithException:[PXTestException failureInRaise: [TRString stringWithCString:#expr] \ exception: nil \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ } while (0) /*" Generates a failure when expression does not throw an exception of a specific class with a specific name. Useful for those frameworks like AppKit or Foundation that throw generic PXTestException w/specific names (NSInvalidArgumentException, etc). _{expression The expression that is evaluated.} _{specificException The specified class of the exception.} _{aName The name of the specified exception.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertThrowsSpecificNamed(expr, specificException, aName, description, ...) \ do { \ @try { \ (expr); \ } \ @catch (specificException *anException) { \ if ([aName isEqualToString: [anException name]]) continue; \ TRString *_descrip = STComposeString("(Expected exception: %@ (name: %@)) %", TRStringFromClass([specificException class]), aName, description); \ [self failWithException: \ [PXTestException failureInRaise: [TRString stringWithCString:#expr] \ exception: anException \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ continue; \ } \ @catch (id anException) { \ TRString *_descrip = STComposeString("(Expected exception: %@) %", TRStringFromClass([specificException class]), description); \ [self failWithException: \ [PXTestException failureInRaise: [TRString stringWithCString:#expr] \ exception: anException \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ continue; \ } \ TRString *_descrip = STComposeString("(Expected exception: %@) %", TRStringFromClass([specificException class]), description); \ [self failWithException: \ [PXTestException failureInRaise: [TRString stringWithCString:#expr] \ exception: nil \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ } while (0) /*" Generates a failure when expression does throw an exception. _{expression The expression that is evaluated.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertNoThrow(expr, description, ...) \ do { \ @try { \ (expr); \ } \ @catch (id anException) { \ [self failWithException:[PXTestException failureInRaise: [TRString stringWithCString:#expr] \ exception: anException \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ } while (0) /*" Generates a failure when expression does throw an exception of the specitied class. Any other exception is okay (i.e. does not generate a failure). _{expression The expression that is evaluated.} _{specificException The specified class of the exception.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertNoThrowSpecific(expr, specificException, description, ...) \ do { \ @try { \ (expr); \ } \ @catch (specificException *anException) { \ [self failWithException:[PXTestException failureInRaise: [TRString stringWithCString:#expr] \ exception: anException \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ } \ @catch (id anythingElse) { \ ; \ } \ } while (0) /*" Generates a failure when expression does throw an exception of a specific class with a specific name. Useful for those frameworks like AppKit or Foundation that throw generic PXTestException w/specific names (NSInvalidArgumentException, etc). _{expression The expression that is evaluated.} _{specificException The specified class of the exception.} _{aName The name of the specified exception.} _{description A format string as in the printf() function. Can be nil or an empty string but must be present.} _{... A variable number of arguments to the format string. Can be absent.} "*/ #define STAssertNoThrowSpecificNamed(expr, specificException, aName, description, ...) \ do { \ @try { \ (expr); \ } \ @catch (specificException *anException) { \ if ([aName isEqualToString: [anException name]]) { \ TRString *_descrip = STComposeString("(Expected exception: %@ (name: %@)) %", TRStringFromClass([specificException class]), aName, description); \ [self failWithException: \ [PXTestException failureInRaise: [TRString stringWithCString:#expr] \ exception: anException \ inFile: [TRString stringWithCString:__FILE__] \ atLine: __LINE__ \ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ } \ continue; \ } \ @catch (id anythingElse) { \ ; \ } \ } while (0) // SENTE_END extern TRString *const SenTestFailureException; extern TRString *const SenTestFilenameKey; extern TRString *const SenTestLineNumberKey; openvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestAssert.m000066400000000000000000000055051332642612100226320ustar00rootroot00000000000000// // Derived from GTMSenTestCase.h // // Copyright 2007-2008 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. // // Portions of this file fall under the following license, marked with // SENTE_BEGIN - SENTE_END // // Copyright (c) 1997-2005, Sen:te (Sente SA). All rights reserved. // // Use of this source code is governed by the following license: // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // (1) Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // (2) Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. // IN NO EVENT SHALL Sente SA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Note: this license is equivalent to the FreeBSD license. // // This notice may not be removed from this file. // Some extra test case macros that would have been convenient for SenTestingKit // to provide. I didn't stick GTM in front of the Macro names, so that they would // be easy to remember. #import #import "PXTestAssert.h" TRString *STComposeString(const char *formatString, ...) { TRString *reason = nil; if (formatString) { va_list vl; va_start(vl, formatString); reason = [[[TRString alloc] initWithFormat:formatString arguments:vl] autorelease]; va_end(vl); } else { reason = [TRString stringWithCString: ""]; } return reason; }openvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestCase.h000066400000000000000000000027341332642612100222400ustar00rootroot00000000000000/* * Author: Landon Fuller * * Copyright (c) 2012 Landon Fuller * Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc. * All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #import "TRObject.h" #import "PXTestAssert.h" #import "PXTestException.h" @interface PXTestCase : TRObject - (void) setUp; - (void) tearDown; - (void) failWithException: (PXTestException *) exception; @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestCase.m000066400000000000000000000034531332642612100222440ustar00rootroot00000000000000/* * Author: Landon Fuller * * Copyright (c) 2012 Landon Fuller * Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc. * All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #import "PXTestCase.h" /** * The test case suite superclass. All test method names must begin with 'test', * and accept no arguments. */ @implementation PXTestCase /** * Perform any test set up. The default implementation is a no-op. */ - (void) setUp { // Do nothing } /** * Perform any test tear down. The default implementation is a no-op. */ - (void) tearDown { // Do nothing } /** * Fail the current test with @a exception. */ - (void) failWithException: (PXTestException *) exception { @throw exception; } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestCaseRunner.h000066400000000000000000000031201332642612100234200ustar00rootroot00000000000000/* * Author: Landon Fuller * Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc. * All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #import "TRObject.h" #import "PXTestCase.h" #import "PXTestResultHandler.h" /** * Implements execution of "test" methods in a PXTestCase. */ @interface PXTestCaseRunner : TRObject { @private id _resultHandler; } - (id) initWithResultHandler: (id) resultHandler; - (BOOL) runAllCases; - (BOOL) runCase: (PXTestCase *) instrumentCase; @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestCaseRunner.m000066400000000000000000000124761332642612100234430ustar00rootroot00000000000000/* * Author: Landon Fuller * Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc. * All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #import #import "TRAutoreleasePool.h" #import "PXTestCaseRunner.h" #import "PXTestObjC.h" /** * Implements runtime detection and execution of PLInstrumentCase instrumentation classes. */ @implementation PXTestCaseRunner /** * Initialize the instrumentation runner with the provided result handler. */ - (id) initWithResultHandler: (id) resultHandler { if ((self = [super init]) == nil) return nil; _resultHandler = [resultHandler retain]; return self; } - (void) dealloc { [_resultHandler release]; [super dealloc]; } /** * Locate all subclasses of PLInstrumentCase registed with the Objective-C runtime, and * execute all instrumentation methods. * * @return Returns YES if all tests were run successfully, or NO if any errors were reported. * * @warning This method may be modified to return a more descriptive object type in the future. */ - (BOOL) runAllCases { Class *classes; int numClasses; /* Get the count of classes */ classes = NULL; numClasses = objc_getClassList(NULL, 0); /* If none, nothing to do */ if (numClasses == 0) return YES; /* Fetch all classes */ classes = malloc(sizeof(Class) * numClasses); numClasses = objc_getClassList(classes, numClasses); BOOL success = YES; for (int i = 0; i < numClasses; i++) { Class cls = classes[i]; Class superClass = cls; BOOL isInstrument = NO; /* Determine if this is a subclass of PXTestCase. By starting with the class * itself, we skip over the non-subclassed PLInstrumentCase class. */ while ((superClass = class_getSuperclass(superClass)) != NULL) { if (superClass == [PXTestCase class]) { isInstrument = YES; break; } } /* If it is an instrument instance, run the tests */ if (isInstrument) { PXTestCase *obj = [[cls alloc] init]; if (![self runCase: obj]) { success = NO; } [obj release]; } } /* Clean up */ free(classes); return success; } /** * Execute all test methods for the given test case. * * @param testCase The test case to run. * @return Returns YES if the test was run successfully, or NO if an error was reported. * * @warning This method may be modified to return a more descriptive object type in the future. */ - (BOOL) runCase: (PXTestCase *) testCase { TRAutoreleasePool *pool = [[TRAutoreleasePool alloc] init]; Method *methods; unsigned int methodCount; /* Inform the result handler of initialization */ [_resultHandler willExecuteTestCase: testCase]; /* Iterate over the available methods */ methods = class_copyMethodList([testCase class], &methodCount); BOOL success = YES; for (unsigned int i = 0; i < methodCount; i++) { Method m; SEL methodSel; char retType[256]; /* Fetch the method meta-data */ m = methods[i]; methodSel = method_getName(m); method_getReturnType(m, retType, sizeof(retType)); /* Only invoke methods that start with the name "test" */ if (strstr(sel_getName(methodSel), "test") == NULL) continue; PXTestException *e = nil; [testCase setUp]; { void (*imp)(id self, SEL _cmd) = (void (*)(id self, SEL _cmd)) method_getImplementation(m); @try { imp(testCase, methodSel); } @catch (PXTestException *re) { success = NO; e = re; } } [testCase tearDown]; /* Inform the result handler of method execution */ if (e != nil) { [_resultHandler didExecuteTestCase: testCase selector: methodSel withException: e]; } else { [_resultHandler didExecuteTestCase: testCase selector: methodSel]; } } /* Inform the result handler of completion */ [_resultHandler didExecuteTestCase: testCase]; /* Clean up */ if (methods != NULL) free(methods); [pool release]; return success; } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestConsoleResultHandler.h000066400000000000000000000025541332642612100254640ustar00rootroot00000000000000/* * Author: Landon Fuller * Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc. * All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include #import "TRObject.h" #import "PXTestResultHandler.h" @interface PXTestConsoleResultHandler : TRObject { @private } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestConsoleResultHandler.m000066400000000000000000000072711332642612100254720ustar00rootroot00000000000000/* * Author: Landon Fuller * Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc. * All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #import "PXTestConsoleResultHandler.h" #import "PXTestObjC.h" #import #import #import #import /** * Console test result handler. All results are output to standard error. */ @implementation PXTestConsoleResultHandler - (TRString *) dateString { struct tm tm; char datestring[256]; setlocale (LC_ALL, ""); time_t now = time(NULL); localtime_r(&now, &tm); size_t bytes = strftime(datestring, sizeof(datestring), nl_langinfo (D_T_FMT), &tm); if (bytes == 0) return nil; return [TRString stringWithCString: datestring]; } // from PXTestResultHandler protocol - (void) willExecuteTestCase: (PXTestCase *) testCase { TRString *output = [TRString stringWithFormat: "Test suite '%s' started at %s\n", class_getName([testCase class]), [[self dateString] cString]]; fprintf(stderr, "%s", [output cString]); } // from PXTestResultHandler protocol - (void) didExecuteTestCase: (PXTestCase *) testCase { TRString *output = [TRString stringWithFormat: "Test suite '%s' finished at %s\n", class_getName([testCase class]), [[self dateString] cString]]; fprintf(stderr, "%s", [output cString]); } // from PXTestResultHandler protocol - (void) didExecuteTestCase: (PXTestCase *) testCase selector: (SEL) selector { TRString *output = [TRString stringWithFormat: "Test case -[%s %s] completed at %s\n", class_getName([testCase class]), sel_getName(selector), [[self dateString] cString]]; fprintf(stderr, "%s", [output cString]); } // from PXTestResultHandler protocol - (void) didExecuteTestCase: (PXTestCase *) testCase selector: (SEL) selector withException: (PXTestException *) exception { TRString *output = [TRString stringWithFormat: "Test case -[%s %s] (%s:%d) failed with error: %s\n", class_getName([testCase class]), sel_getName(selector), [[exception fileName] cString], [exception lineNumber], [[exception reason] cString]]; fprintf(stderr, "%s", [output cString]); } // from PXTestResultHandler protocol - (void) didSkipTestCase: (PXTestCase *) testCase selector: (SEL) selector reason: (TRString *) reason { TRString *output = [TRString stringWithFormat: "Test case -[%s %s] failed (%s) at %s\n", class_getName([testCase class]), sel_getName(selector), [reason cString], [[self dateString] cString]]; fprintf(stderr, "%s", [output cString]); } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestException.h000066400000000000000000000107021332642612100233150ustar00rootroot00000000000000// // File derived from: GTMSenTestCase.h // // Copyright 2007-2008 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. // // Portions of this file fall under the following license, marked with // SENTE_BEGIN - SENTE_END // // Copyright (c) 1997-2005, Sen:te (Sente SA). All rights reserved. // // Use of this source code is governed by the following license: // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // (1) Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // (2) Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. // IN NO EVENT SHALL Sente SA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT // OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Note: this license is equivalent to the FreeBSD license. // // This notice may not be removed from this file. #import "TRObject.h" #import "TRString.h" @interface PXTestException : TRObject { @private /** The test failure reason. */ TRString *_reason; /** The test failure file name. */ TRString *_fileName; /** The line number at which the test failure was thrown. */ int _lineNumber; } + (PXTestException *)failureInFile:(TRString *)filename atLine:(int)lineNumber withDescription:(TRString *)formatString, ...; + (PXTestException *)failureInCondition:(TRString *)condition isTrue:(BOOL)isTrue inFile:(TRString *)filename atLine:(int)lineNumber withDescription:(TRString *)formatString, ...; + (PXTestException *)failureInEqualityBetweenObject:(id)left andObject:(id)right inFile:(TRString *)filename atLine:(int)lineNumber withDescription:(TRString *)formatString, ...; + (PXTestException *)failureInEqualityBetweenValue:(id)left andValue:(id)right withAccuracy:(id)accuracy inFile:(TRString *)filename atLine:(int) ineNumber withDescription:(TRString *)formatString, ...; + (PXTestException *)failureInRaise:(TRString *)expression inFile:(TRString *)filename atLine:(int)lineNumber withDescription:(TRString *)formatString, ...; + (PXTestException *)failureInRaise:(TRString *)expression exception:(PXTestException *)exception inFile:(TRString *)filename atLine:(int)lineNumber withDescription:(TRString *)formatString, ...; - (id) initWithReason: (TRString *) reason fileName: (TRString *) fileName lineNumber: (int) lineNumber; - (TRString *) reason; - (TRString *) fileName; - (int) lineNumber; @endopenvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestException.m000066400000000000000000000177711332642612100233370ustar00rootroot00000000000000// // File derived from: GTMSenTestCase.m // // Copyright 2007-2008 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy // of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. // #import #import "PXTestException.h" @interface PXTestException (PrivateMethods) + (PXTestException *)failureInFile:(TRString *)filename atLine:(int)lineNumber reason:(TRString *)reason; @end /** * A test case exception. Provides API required by the SenTestCase-compatible assertion macros. */ @implementation PXTestException + (PXTestException *)failureInFile:(TRString *)filename atLine:(int)lineNumber withDescription:(TRString *)formatString, ... { TRString *testDescription = nil; if (formatString) { va_list vl; va_start(vl, formatString); testDescription = [[[TRString alloc] initWithFormat:[formatString cString] arguments:vl] autorelease]; va_end(vl); } else { testDescription = [TRString stringWithCString: ""]; } TRString *reason = testDescription; return [self failureInFile:filename atLine:lineNumber reason:reason]; } + (PXTestException *)failureInCondition:(TRString *)condition isTrue:(BOOL)isTrue inFile:(TRString *)filename atLine:(int)lineNumber withDescription:(TRString *)formatString, ... { TRString *testDescription = nil; if (formatString) { va_list vl; va_start(vl, formatString); testDescription = [[[TRString alloc] initWithFormat:[formatString cString] arguments:vl] autorelease]; va_end(vl); } else { testDescription = [TRString stringWithCString: ""]; } TRString *reason = [TRString stringWithFormat:"'%s' should be %s. %s", [condition cString], isTrue ? "false" : "true", [testDescription cString] ]; return [self failureInFile:filename atLine:lineNumber reason:reason]; } + (PXTestException *)failureInEqualityBetweenObject:(id)left andObject:(id)right inFile:(TRString *)filename atLine:(int)lineNumber withDescription:(TRString *)formatString, ... { TRString *testDescription = nil; if (formatString) { va_list vl; va_start(vl, formatString); testDescription = [[[TRString alloc] initWithFormat:[formatString cString] arguments:vl] autorelease]; va_end(vl); } else { testDescription = [TRString stringWithCString: ""]; } // XXX - We need to support -description here #if TODO_TRSTRING_FORMAT TRString *reason = [TRString stringWithFormat:"'%@' should be equal to '%@'. %s", [left description], [right description], [testDescription cString]]; #else TRString *reason = [TRString stringWithFormat:"'%p' should be equal to '%p'. %s", left, right, [testDescription cString]]; #endif return [self failureInFile:filename atLine:lineNumber reason:reason]; } + (PXTestException *)failureInEqualityBetweenValue:(id)left andValue:(id)right withAccuracy:(id)accuracy inFile:(TRString *)filename atLine:(int)lineNumber withDescription:(TRString *)formatString, ... { TRString *testDescription = nil; if (formatString) { va_list vl; va_start(vl, formatString); testDescription = [[[TRString alloc] initWithFormat:[formatString cString] arguments:vl] autorelease]; va_end(vl); } else { testDescription = [TRString stringWithCString: ""]; } TRString *reason; // XXX - We need to support -description here #if TODO_TRSTRING_FORMAT if (accuracy) { reason = [TRString stringWithFormat:"'%@' should be equal to '%@'. %@", left, right, testDescription]; } else { reason = [TRString stringWithFormat:"'%@' should be equal to '%@' +/-'%@'. %@", left, right, accuracy, testDescription]; } #else /* HAVE_FRAMEWORK_FOUNDATION */ if (accuracy) { reason = [TRString stringWithFormat:"'%p' should be equal to '%p'. %s", left, right, [testDescription cString]]; } else { reason = [TRString stringWithFormat:"'%p' should be equal to '%p' +/-'%p'. %s", left, right, accuracy, [testDescription cString]]; } #endif return [self failureInFile:filename atLine:lineNumber reason:reason]; } + (PXTestException *)failureInRaise:(TRString *)expression inFile:(TRString *)filename atLine:(int)lineNumber withDescription:(TRString *)formatString, ... { TRString *testDescription = nil; if (formatString) { va_list vl; va_start(vl, formatString); testDescription = [[[TRString alloc] initWithFormat:[formatString cString] arguments:vl] autorelease]; va_end(vl); } else { testDescription = [TRString stringWithCString: ""]; } TRString *reason = [TRString stringWithFormat:"'%s' should raise. %s", [expression cString], [testDescription cString]]; return [self failureInFile:filename atLine:lineNumber reason:reason]; } + (PXTestException *)failureInRaise:(TRString *)expression exception:(PXTestException *)exception inFile:(TRString *)filename atLine:(int)lineNumber withDescription:(TRString *)formatString, ... { TRString *testDescription = nil; if (formatString) { va_list vl; va_start(vl, formatString); testDescription = [[[TRString alloc] initWithFormat:[formatString cString] arguments:vl] autorelease]; va_end(vl); } else { testDescription = [TRString stringWithCString: ""]; } TRString *reason; if ([exception isKindOfClass: [PXTestException class]]) { // it's our exception, assume it has the right description on it. reason = [exception reason]; } else { // not one of our exception, use the exceptions reason and our description reason = [TRString stringWithFormat:"'%s' raised '%s'. %s", [expression cString], [[exception reason] cString], [testDescription cString]]; } return [self failureInFile:filename atLine:lineNumber reason:reason]; } /** * Initialize a new test failure exception. * * @param reason The test failure reason. * @param fileName The test failure file name. * @param lineNumber The line number at which the test failure was thrown. */ - (id) initWithReason: (TRString *) reason fileName: (TRString *) fileName lineNumber: (int) lineNumber { if ((self = [super init]) == nil) return nil; _reason = [reason retain]; _fileName = [fileName retain]; _lineNumber = lineNumber; return self; } - (void) dealloc { [_reason release]; [_fileName release]; [super dealloc]; } /** * Return the test failure reason. */ - (TRString *) reason { return _reason; } /** * Return the file name containing the failed test. */ - (TRString *) fileName { return _fileName; } /** * Return the line number at which the test failure was thrown. */ - (int) lineNumber { return _lineNumber; } @end @implementation PXTestException (GTMSenTestPrivateAdditions) + (PXTestException *)failureInFile:(TRString *)filename atLine:(int)lineNumber reason:(TRString *)reason { return [[[self alloc] initWithReason: reason fileName: filename lineNumber: lineNumber] autorelease]; } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestObjC.h000066400000000000000000000023431332642612100221760ustar00rootroot00000000000000/* * Author: Landon Fuller * Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc. * All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #import openvpn-auth-ldap-auth-ldap-2.0.4/tests/PXTestResultHandler.h000066400000000000000000000052241332642612100241360ustar00rootroot00000000000000/* * Author: Landon Fuller * Copyright (c) 2008 Plausible Labs Cooperative, Inc. * All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #import "TRObject.h" #import "PXTestException.h" #import "PXTestCase.h" #import "TRString.h" /** * Provides handling of test results. The results may be printed * to stderr, output as XML, etc. */ @protocol PXTestResultHandler /** * Called when preparing to execute a test case. * * @param testCase The test case to be executed */ - (void) willExecuteTestCase: (PXTestCase *) testCase; /** * Called when finished to executing a test case. */ - (void) didExecuteTestCase: (PXTestCase *) testCase; /** * Called upon successful execution of an test case's test method. * * @param testCase The executed test case instance. * @param selector The selector executed. */ - (void) didExecuteTestCase: (PXTestCase *) testCase selector: (SEL) selector; /** * Called upon failed execution of an test case's test method. * * @param testCase The executed test case instance. * @param selector The selector executed. * @param exception The failure cause. */ - (void) didExecuteTestCase: (PXTestCase *) testCase selector: (SEL) selector withException: (PXTestException *) exception; /** * If an test method can not be run, this method will be called. * * @param testCase The executed test case instance. * @param selector The selector executed. * @param reason Non-localized human readable reason that the instrumentation method was skipped. */ - (void) didSkipTestCase: (PXTestCase *) testCase selector: (SEL) selector reason: (TRString *) reason; @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/TRArrayTests.m000066400000000000000000000122101332642612100226170ustar00rootroot00000000000000/* * TRArray.m vi:ts=4:sw=4:expandtab: * TRArray Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * Copyright (c) 2012 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import "TRArray.h" #import "TRString.h" @interface TRArrayTests : PXTestCase @end @implementation TRArrayTests - (void) test_addObject { TRArray *array = [[TRArray alloc] init]; TRString *string1 = [[TRString alloc] initWithCString: "String 1"]; TRString *string2 = [[TRString alloc] initWithCString: "String 2"]; TRString *string3 = [[TRString alloc] initWithCString: "String 3"]; /* Add 3 items to the array */ [array addObject: string1]; fail_unless([array lastObject] == string1); fail_unless([string1 retainCount] == 2); [array addObject: string2]; fail_unless([array lastObject] == string2); fail_unless([string2 retainCount] == 2); [array addObject: string3]; fail_unless([array lastObject] == string3); fail_unless([string3 retainCount] == 2); /* Clean up the array */ [array release]; /* Verify that the array released all objects */ fail_unless([string1 retainCount] == 1); fail_unless([string2 retainCount] == 1); fail_unless([string3 retainCount] == 1); /* Clean up our remaining objects */ [string1 release]; [string2 release]; [string3 release]; } - (void) test_removeObject { TRArray *array = [[TRArray alloc] init]; TRString *string1 = [[TRString alloc] initWithCString: "String 1"]; TRString *string2 = [[TRString alloc] initWithCString: "String 2"]; /* Fill our array */ [array addObject: string1]; [array addObject: string2]; /* Pop an object off the stack */ fail_unless([array lastObject] == string2); [array removeObject]; fail_unless([array lastObject] == string1); [array removeObject]; fail_unless([array lastObject] == nil); [array release]; [string1 release]; [string2 release]; } - (void) test_containsObject { TRArray *array = [[TRArray alloc] init]; TRString *string1 = [[TRString alloc] initWithCString: "String 1"]; /* Fill our array */ [array addObject: string1]; /* Look for our object */ STAssertTrue([array containsObject: string1], "Array claims to not contain the added object."); /* And a known bad one ... */ STAssertFalse([array containsObject: array], "Array claims to contain itself."); [array release]; [string1 release]; } - (void) test_count { TRArray *array = [[TRArray alloc] init]; TRString *string1 = [[TRString alloc] initWithCString: "String 1"]; /* Fill our array */ [array addObject: string1]; /* Check the count */ fail_unless([array count] == 1); [array release]; [string1 release]; } - (void) test_objectEnumerator { TRArray *array = [[TRArray alloc] init]; TRString *string1 = [[TRString alloc] initWithCString: "String 1"]; TRString *string2 = [[TRString alloc] initWithCString: "String 2"]; TREnumerator *iter; id obj; /* Insert */ [array addObject: string1]; [array addObject: string2]; /* Grab an enumerator */ iter = [array objectEnumerator]; obj = [iter nextObject]; fail_unless(obj == string2); obj = [iter nextObject]; fail_unless(obj == string1); /* Grab a reverse enumerator */ iter = [array objectReverseEnumerator]; obj = [iter nextObject]; fail_unless(obj == string1); obj = [iter nextObject]; fail_unless(obj == string2); /* Clean up */ [array release]; [string1 release]; [string2 release]; } @endopenvpn-auth-ldap-auth-ldap-2.0.4/tests/TRAuthLDAPConfigTests.m000066400000000000000000000116331332642612100242410ustar00rootroot00000000000000/* * TRAuthLDAPConfig.m vi:ts=4:sw=4:expandtab: * TRAuthLDAPConfig Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import #import "PXTestCase.h" #import "TRAuthLDAPConfig.h" #import "tests.h" /* Data Constants */ #define TEST_LDAP_URL "ldap://ldap1.example.org" #define TEST_LDAP_TIMEOUT 15 #define TEST_LDAP_BASEDN "ou=People,dc=example,dc=com" @interface TRAuthLDAPConfigTests : PXTestCase @end @implementation TRAuthLDAPConfigTests - (void) test_initWithConfigFile { TRAuthLDAPConfig *config; TRString *string; config = [[TRAuthLDAPConfig alloc] initWithConfigFile: AUTH_LDAP_CONF]; fail_if(config == NULL, "-[[TRAuthLDAPConfig alloc] initWithConfigFile:] returned NULL"); /* Validate the parsed settings */ string = [config url]; fail_if(!string, "-[TRAuthLDAPConfig url] returned NULL"); fail_unless(strcmp([string cString], TEST_LDAP_URL) == 0, "-[TRAuthLDAPConfig url] returned incorrect value. (Expected %s, Got %s)", TEST_LDAP_URL, [string cString]); fail_unless([config timeout] == TEST_LDAP_TIMEOUT); fail_unless([config tlsEnabled]); fail_if([config ldapGroups] == nil); fail_if([[config ldapGroups] lastObject] == nil); #ifdef HAVE_PF fail_unless([config pfEnabled]); #endif [config release]; } - (void) test_initWithIncorrectlyNamedSection { TRAuthLDAPConfig *config; config = [[TRAuthLDAPConfig alloc] initWithConfigFile: AUTH_LDAP_CONF_NAMED]; fail_if(config != NULL, "-[[TRAuthLDAPConfig alloc] initWithConfigFile:] accepted a named LDAP section."); [config release]; } - (void) test_initWithMismatchedSection { TRAuthLDAPConfig *config; config = [[TRAuthLDAPConfig alloc] initWithConfigFile: AUTH_LDAP_CONF_MISMATCHED]; fail_if(config != NULL, "-[[TRAuthLDAPConfig alloc] initWithConfigFile:] accepted a mismatched section closure."); [config release]; } - (void) test_initWithDuplicateKeys { TRAuthLDAPConfig *config; config = [[TRAuthLDAPConfig alloc] initWithConfigFile: AUTH_LDAP_CONF_MULTIKEY]; fail_if(config != NULL, "-[[TRAuthLDAPConfig alloc] initWithConfigFile:] accepted duplicate keys."); [config release]; } - (void) test_initWithMissingKey { TRAuthLDAPConfig *config; config = [[TRAuthLDAPConfig alloc] initWithConfigFile: AUTH_LDAP_CONF_REQUIRED]; fail_if(config != NULL, "-[[TRAuthLDAPConfig alloc] initWithConfigFile:] accepted a missing required key."); [config release]; } - (void) test_initWithMissingTrailingNewline { TRAuthLDAPConfig *config; TRString *baseDN; config = [[TRAuthLDAPConfig alloc] initWithConfigFile: AUTH_LDAP_CONF_MISSING_NEWLINE]; fail_if(config == NULL, "-[[TRAuthLDAPConfig alloc] initWithConfigFile:] did not parse a file missing a trailing newline"); /* Verify that the final section was parsed */ baseDN = [config baseDN]; fail_unless(strcmp([baseDN cString], TEST_LDAP_BASEDN) == 0, "-[TRAuthLDAPConfig baseDN] returned incorrect value (got '%s', expected '%s')", [[config baseDN] cString], TEST_LDAP_BASEDN); [config release]; } - (void) test_initWithBadSection { TRAuthLDAPConfig *config; config = [[TRAuthLDAPConfig alloc] initWithConfigFile: AUTH_LDAP_CONF_BAD_SECTION]; fail_if(config != NULL, "-[[TRAuthLDAPConfig alloc] initWithConfigFile:] accepted an invalid section."); } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/TRAutoreleasePoolTests.m000066400000000000000000000037561332642612100246630ustar00rootroot00000000000000/* * TRAutoreleasePool.m vi:ts=4:sw=4:expandtab: * * Copyright (C) 2005 - 2007 Landon Fuller * All rights reserved. * * This file is part of Objective-C Substrate. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. * * We disclaim all warranties with regard to this software, including all * implied warranties of merchantability and fitness, in no event shall * we be liable for any special, indirect or consequential damages or any * damages whatsoever resulting from loss of use, data or profits, whether in * an action of contract, negligence or other tortious action, arising out of * or in connection with the use or performance of this software. */ #import "TRAutoreleasePool.h" #import "PXTestCase.h" static unsigned int livecount; @interface PoolTester : TRObject @end @implementation PoolTester - (oneway void) release { livecount--; [super release]; } - (void) dealloc { livecount--; [super dealloc]; } @end @interface TRAutoreleasePoolTests : PXTestCase @end @implementation TRAutoreleasePoolTests - (void) testAddObject { TRAutoreleasePool *pool; TRObject *obj; int i; /* Allocate a pool */ pool = [[TRAutoreleasePool alloc] init]; fail_if(pool == nil, "[[TRAutoreleasePool alloc] init] returned nil.\n"); /* Allocate an object to auto-release */ obj = [[PoolTester alloc] init]; [obj autorelease]; /* Implicit refcount + dealloc */ livecount = 2; /* Exercise the pool */ for (i = 0; i < 4096; i++) { livecount++; [obj retain]; [obj autorelease]; } /* Release it */ [pool release]; fail_unless(livecount == 0, "[TRAutoreleasePool release] failed to release %d objects.", livecount); } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/TRConfigLexerTests.m000066400000000000000000000064611332642612100237610ustar00rootroot00000000000000/* * TRConfigLexer.m vi:ts=4:sw=4:expandtab: * TRConfigLexer Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import #import #import #import "TRConfig.h" #import "TRConfigParser.h" #import "TRConfigLexer.h" #import "PXTestCase.h" #import "tests.h" /* Path Constants */ #define TEST_CONF DATA_PATH("test-lineNumbers.conf") @interface TRConfigLexerTests : PXTestCase @end @implementation TRConfigLexerTests - (void) testParse { TRConfigLexer *lexer; TRConfigToken *token; int configFD; /* Open our configuration file */ configFD = open(TEST_CONF, O_RDONLY); fail_if(configFD == -1, "open() returned -1"); lexer = [[TRConfigLexer alloc] initWithFD: configFD]; fail_if(lexer == NULL, "-[[TRConfigLexer alloc] initWithFD:] returned NULL"); while ((token = [lexer scan]) != NULL) { /* The configuration file was assembled so that all values match the, * current line number -- that is to say, for any given key/value pair, * the value is set to the current line number of that pair. */ if ([token tokenID] == TOKEN_VALUE || [token tokenID] == TOKEN_SECTION_NAME || [token tokenID] == TOKEN_SECTION_START) { int value; /* Get the integer representation */ fail_unless([token intValue: &value], "-[TRConfigToken getIntValue:] returned false. (String Value: %s)", [token cString]); /* Verify that the line number is correct */ fail_unless(value == [token lineNumber], "-[TRConfigToken getLineNumber] out of sync. (Expected %d, got %d)", value, [token lineNumber]); } [token dealloc]; } close(configFD); [lexer dealloc]; } @endopenvpn-auth-ldap-auth-ldap-2.0.4/tests/TRConfigTests.m000066400000000000000000000066211332642612100227570ustar00rootroot00000000000000/* * TRConfig.m vi:ts=4:sw=4:expandtab: * TRConfig Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import #import #import "tests.h" #import "TRConfig.h" /* Path Constants */ #define TEST_CONF DATA_PATH("TRConfig.conf") /* * Mock configuration delegate */ @interface MockConfigDelegate : TRObject - (void) setKey: (TRConfigToken *) key value: (TRConfigToken *) value; - (void) startSection: (TRConfigToken *) type sectionName: (TRConfigToken *) name; - (void) endSection: (TRConfigToken *) sectionEnd; - (void) parseError: (TRConfigToken *) badToken; @end @implementation MockConfigDelegate - (void) setKey: (TRConfigToken *) key value: (TRConfigToken *) value { /* Do nothing */ return; } - (void) startSection: (TRConfigToken *) type sectionName: (TRConfigToken *) name { /* Do nothing */ return; } - (void) endSection: (TRConfigToken *) sectionEnd { /* Do nothing */ return; } - (void) parseError: (TRConfigToken *) badToken { /* Do nothing */ return; } @end @interface TRConfigTests : PXTestCase @end @implementation TRConfigTests - (void) testInitWithFD { TRConfig *config; MockConfigDelegate *delegate; int configFD; /* Open our configuration file */ configFD = open(TEST_CONF, O_RDONLY); fail_if(configFD == -1, "open() returned -1"); /* Initialize the configuration parser */ delegate = [[MockConfigDelegate alloc] init]; config = [[TRConfig alloc] initWithFD: configFD configDelegate: delegate]; fail_if(config == NULL, "-[[TRConfig alloc] initWithFD:] returned NULL"); /* Parse the configuration file */ fail_unless([config parseConfig], "-[TRConfig parse] returned NULL"); /* Clean up */ [delegate release]; close(configFD); } @endopenvpn-auth-ldap-auth-ldap-2.0.4/tests/TRConfigTokenTests.m000066400000000000000000000105041332642612100237530ustar00rootroot00000000000000/* * TRConfigToken.m vi:ts=4:sw=4:expandtab: * TRConfigToken Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import "TRConfigToken.h" #import "TRConfig.h" #import "TRConfigParser.h" #import #define TEST_STRING "The answer to life, the universe, and everything" #define TEST_LINE_NUMBER 42 @interface TRConfigTokenTests : PXTestCase @end @implementation TRConfigTokenTests - (void) test_initWithBytes { int tokenID; unsigned int lineNumber; TRConfigToken *token; token = [[TRConfigToken alloc] initWithBytes: TEST_STRING numBytes: sizeof(TEST_STRING) lineNumber: TEST_LINE_NUMBER tokenID: TOKEN_VALUE]; fail_if(token == NULL, "-[[TRConfigToken alloc] initWithBytes: numBytes: tokenID:] returned NULL"); tokenID = [token tokenID]; fail_unless(tokenID == TOKEN_VALUE, "-[TRConfigToken tokenID] returned incorrect value. (Expected %d, got %d)", tokenID, TOKEN_VALUE); lineNumber = [token lineNumber]; fail_unless(lineNumber == TEST_LINE_NUMBER, "-[TRConfigToken lineNumber] returned incorrect value. (Expected %d, got %d)", TEST_LINE_NUMBER, lineNumber); [token release]; } - (void) test_intValue { TRConfigToken *token; int value; token = [[TRConfigToken alloc] initWithBytes: "24" numBytes: sizeof("24") lineNumber: TEST_LINE_NUMBER tokenID: TOKEN_VALUE]; fail_if(token == NULL, "-[[TRConfigToken alloc] initWithBytes: numBytes: tokenID:] returned NULL"); fail_unless([token intValue: &value], "-[TRConfigToken intValue:] returned NO"); fail_unless(value == 24, "-[TRConfigToken value] returned incorrect value. (Expected %d, got %d)", 24, value); [token release]; } - (void) test_boolValue { TRConfigToken *token; BOOL value; token = [[TRConfigToken alloc] initWithBytes: "yes" numBytes: sizeof("yes") lineNumber: TEST_LINE_NUMBER tokenID: TOKEN_VALUE]; fail_unless([token boolValue: &value], "-[TRConfigToken boolValue:] returned NO"); fail_unless(value == YES, "-[TRConfigToken value] returned incorrect value. (Expected %d, got %d)", YES, value); [token release]; token = [[TRConfigToken alloc] initWithBytes: "no" numBytes: sizeof("no") lineNumber: TEST_LINE_NUMBER tokenID: TOKEN_VALUE]; fail_unless([token boolValue: &value], "-[TRConfigToken boolValue:] returned NO"); fail_unless(value == NO, "-[TRConfigToken value] returned incorrect value. (Expected %d, got %d)", NO, value); [token release]; } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/TRHashTests.m000066400000000000000000000124561332642612100224400ustar00rootroot00000000000000/* * TRHash.m vi:ts=4:sw=4:expandtab: * TRHash Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import "TRHash.h" @interface TRHashTests : PXTestCase @end @implementation TRHashTests - (void) testInitWithCapacity { TRHash *hash = [[TRHash alloc] initWithCapacity: 42]; [hash release]; } - (void) testIsFull { TRHash *hash = [[TRHash alloc] initWithCapacity: 0]; fail_unless([hash isFull]); [hash release]; } - (void) test_setObjectForKey { TRHash *hash = [[TRHash alloc] initWithCapacity: 1]; TRString *string = [[TRString alloc] initWithCString: "Hello, World"]; size_t refCount = [string retainCount]; [hash setObject: string forKey: string]; /* Verify that the object has been retained twice: * - Once as the value * - Once as the key */ fail_unless([string retainCount] == refCount + 2); /* Release our hash table */ [hash release]; /* Verify that the object has been released */ fail_unless([string retainCount] == refCount); [string release]; } /* * Verifies that replacing a key correctly releases key and associated value */ - (void) test_setObjectForKey_replacement { TRHash *hash = [[TRHash alloc] initWithCapacity: 1]; TRString *key = [[TRString alloc] initWithCString: "Key"]; TRString *value1 = [[TRString alloc] initWithCString: "Hello, World"]; TRString *value2 = [[TRString alloc] initWithCString: "Goodbye, World"]; size_t refCount = [key retainCount]; /* Insert value1 */ [hash setObject: value1 forKey: key]; fail_unless([key retainCount] == refCount + 1); /* Replace the node */ [hash setObject: value2 forKey: key]; fail_unless([key retainCount] == refCount + 1); fail_unless([value1 retainCount] == refCount); [hash release]; /* Verify that the objects have been released */ fail_unless([key retainCount] == refCount); fail_unless([value1 retainCount] == refCount); fail_unless([value2 retainCount] == refCount); [key release]; [value1 release]; [value2 release]; } - (void) test_removeObjectForKey { TRHash *hash = [[TRHash alloc] initWithCapacity: 1]; TRString *key = [[TRString alloc] initWithCString: "Key"]; TRString *value = [[TRString alloc] initWithCString: "Value"]; PXUInteger refCount = [key retainCount]; /* Insert */ [hash setObject: value forKey: key]; /* Remove */ [hash removeObjectForKey: key]; /* Validate refCounts */ fail_unless([key retainCount] == refCount); fail_unless([value retainCount] == refCount); /* Clean up */ [key release]; [value release]; [hash release]; } - (void) test_valueForKey { TRHash *hash = [[TRHash alloc] initWithCapacity: 1]; TRString *key = [[TRString alloc] initWithCString: "Key"]; TRString *value = [[TRString alloc] initWithCString: "Value"]; /* Insert */ [hash setObject: value forKey: key]; /* Get value */ fail_unless([hash valueForKey: key] == value); /* Clean up */ [hash release]; [key release]; [value release]; } - (void) test_keyEnumerator { TRHash *hash = [[TRHash alloc] initWithCapacity: HASHCOUNT_T_MAX]; TRString *key = [[TRString alloc] initWithCString: "Key"]; TRString *value = [[TRString alloc] initWithCString: "Value"]; TREnumerator *iter; id obj; /* Insert */ [hash setObject: value forKey: key]; [hash setObject: key forKey: value]; /* Grab an enumerator */ iter = [hash keyEnumerator]; obj = [iter nextObject]; fail_unless(obj == value || obj == key); obj = [iter nextObject]; fail_unless(obj == value || obj == key); /* Clean up */ [hash release]; [key release]; [value release]; } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/TRLDAPAccountRepositoryTests.m000066400000000000000000000057771332642612100257220ustar00rootroot00000000000000/* * TRLDAPAccountRepositoryTests.m vi:ts=4:sw=4:expandtab: * TRLDAPAccountRepository Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import "TRLDAPAccountRepository.h" #import "TRAuthLDAPConfig.h" #import "tests.h" @interface TRLDAPAccountRepositoryTests : PXTestCase @end @implementation TRLDAPAccountRepositoryTests - (void) test_initWithLDAPConnection { TRLDAPAccountRepository *accounts; TRAuthLDAPConfig *config; TRLDAPConnection *conn; /* Set up a TRLDAPConnection */ config = [[TRAuthLDAPConfig alloc] initWithConfigFile: AUTH_LDAP_CONF]; fail_if(config == nil, "-[[TRAuthLDAPConfig alloc] initWithConfigFile:] returned nil"); conn = [[TRLDAPConnection alloc] initWithURL: [config url] timeout: [config timeout]]; /* Initialize a TRLDAPAccountRepository */ TRLDAPSearchFilter *userFilter = [[[TRLDAPSearchFilter alloc] initWithFormat: [TRString stringWithCString: "%s"]] autorelease]; TRLDAPSearchFilter *groupFilter = [[[TRLDAPSearchFilter alloc] initWithFormat: [TRString stringWithCString: "%s"]] autorelease]; accounts = [[TRLDAPAccountRepository alloc] initWithLDAPConnection: conn userSearchFilter: userFilter groupSearchFilter: groupFilter]; fail_if(accounts == nil, "-[[TRLDAPAccountRepository alloc] initWithLDAPConnection:] returned nil"); [accounts release]; [config release]; [conn release]; } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/TRLDAPConnectionTests.m000066400000000000000000000061061332642612100243100ustar00rootroot00000000000000/* * TRLDAPConnection.m vi:ts=4:sw=4:expandtab: * TRLDAPConnection Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import "TRLDAPConnection.h" #import "TRAuthLDAPConfig.h" #import #import "tests.h" /* Data Constants */ #define TEST_LDAP_URL "ldap://ldap1.example.org" #define TEST_LDAP_TIMEOUT 15 @interface TRLDAPConnectionTests : PXTestCase @end @implementation TRLDAPConnectionTests - (void) testInit { TRAuthLDAPConfig *config; TRLDAPConnection *conn; TRString *value; config = [[TRAuthLDAPConfig alloc] initWithConfigFile: AUTH_LDAP_CONF]; fail_if(config == NULL, "-[[TRAuthLDAPConfig alloc] initWithConfigFile:] returned NULL"); conn = [[TRLDAPConnection alloc] initWithURL: [config url] timeout: [config timeout]]; /* Referrals */ fail_unless([conn setReferralEnabled: [config referralEnabled]]); /* Certificate file */ if ((value = [config tlsCACertFile])) fail_unless([conn setTLSCACertFile: value]); /* Certificate directory */ if ((value = [config tlsCACertDir])) fail_unless([conn setTLSCACertDir: value]); /* Client Certificate Pair */ if ([config tlsCertFile] && [config tlsKeyFile]) fail_unless([conn setTLSClientCert: [config tlsCertFile] keyFile: [config tlsKeyFile]]); /* Cipher suite */ if ((value = [config tlsCipherSuite])) fail_unless([conn setTLSCipherSuite: value]); [config release]; [conn release]; } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/TRLDAPEntryTests.m000066400000000000000000000045551332642612100233200ustar00rootroot00000000000000/* * TRLDAPEntry.m vi:ts=4:sw=4:expandtab: * TRLDAPEntry Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import "TRLDAPEntry.h" @interface TRLDAPEntryTests : PXTestCase @end @implementation TRLDAPEntryTests - (void) testInitWithDN { TRLDAPEntry *entry; TRString *dn; TRHash *attributes; dn = [[TRString alloc] initWithCString: "dc=foobar"]; /* Make something up for the attributes */ attributes = [[TRHash alloc] initWithCapacity: 1]; [attributes setObject: dn forKey: dn]; entry = [[TRLDAPEntry alloc] initWithDN: dn attributes: attributes]; fail_unless([entry attributes] == attributes); fail_unless([entry dn] == dn); [entry release]; [dn release]; [attributes release]; } @endopenvpn-auth-ldap-auth-ldap-2.0.4/tests/TRLDAPGroupConfigTests.m000066400000000000000000000040771332642612100244400ustar00rootroot00000000000000/* * TRLDAPGroupConfig.m vi:ts=4:sw=4:expandtab: * TRLDAPGroundConfig Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import "TRLDAPGroupConfig.h" /* Data Constants */ #define TEST_LDAP_BASEDN "ou=People,dc=example,dc=com" #define TEST_LDAP_ATTRIBUTE "uniqueMember" #define TEST_LDAP_FILTER "(|(cn=artists)(cn=engineers))" @interface TRLDAPGroupConfigTests : PXTestCase @end @implementation TRLDAPGroupConfigTests // TODO @endopenvpn-auth-ldap-auth-ldap-2.0.4/tests/TRLDAPSearchFilterTests.m000066400000000000000000000061501332642612100245630ustar00rootroot00000000000000/* * TRLDAPSearchFilter.m vi:ts=4:sw=4:expandtab: * TRLDAPSearchFilter Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import #import "TRLDAPSearchFilter.h" @interface TRLDAPSearchFilterTests : PXTestCase @end @implementation TRLDAPSearchFilterTests - (void) test_initWithFormat { TRLDAPSearchFilter *filter = [[TRLDAPSearchFilter alloc] initWithFormat: [TRString stringWithCString: "%s foo"]]; [filter release]; } - (void) test_getFilter { TRLDAPSearchFilter *filter = [[TRLDAPSearchFilter alloc] initWithFormat: [TRString stringWithCString: "(&(uid=%s)(cn=%s))"]]; const char *expected = "(&(uid=fred)(cn=fred))"; TRString *result = [filter getFilter: [TRString stringWithCString: "fred"]]; fail_unless(strcmp([result cString], expected) == 0, "-[TRLDAPSearchFilter createFilter:] returned incorrect string. (Expected %s, got %s)", expected, [result cString]); [filter release]; } - (void) test_ldapEscaping { TRLDAPSearchFilter *filter = [[TRLDAPSearchFilter alloc] initWithFormat: [TRString stringWithCString: "(%s)"]]; const char *expected = "(\\(foo\\*\\)\\\\)"; /* Pass in something containing all the special characters */ TRString *result = [filter getFilter: [TRString stringWithCString: "(foo*)\\"]]; fail_unless(strcmp([result cString], expected) == 0, "-[TRLDAPSearchFilter createFilter:] returned incorrect string. (Expected %s, got %s)", expected, [result cString]); [filter release]; } @endopenvpn-auth-ldap-auth-ldap-2.0.4/tests/TRLocalPacketFilterTests.m000066400000000000000000000144101332642612100250750ustar00rootroot00000000000000/* * TRLocalPacketFilter.m vi:ts=4:sw=4:expandtab: * TRLocalPacketFilter Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #ifdef HAVE_PF #import #import "TRLocalPacketFilter.h" #import "mockpf.h" static TRLocalPacketFilter *pf = nil; void setUp(void) { mockpf_setup(); pf = [[TRLocalPacketFilter alloc] init]; [pf open]; } void tearDown(void) { mockpf_teardown(); [pf release]; pf = nil; } START_TEST(test_init) { fail_if(pf == nil); } END_TEST START_TEST(test_tables) { TRArray *tables; TREnumerator *tableIter; fail_unless([pf tables: &tables] == PF_SUCCESS); /* Assume a few things about our mock pf implementation */ tableIter = [tables objectEnumerator]; fail_unless(strcmp([[tableIter nextObject] cString], "ips_artist") == 0); fail_unless(strcmp([[tableIter nextObject] cString], "ips_developer") == 0); } END_TEST START_TEST(test_flushTable) { TRString *name = [[TRString alloc] initWithCString: "ips_artist"]; fail_unless([pf flushTable: name] == PF_SUCCESS); [name release]; } END_TEST START_TEST(test_addAddressToTable) { TRString *addrString; TRPFAddress *pfAddress; TRArray *addresses; TRString *name; name = [[TRString alloc] initWithCString: "ips_artist"]; fail_unless([pf flushTable: name] == PF_SUCCESS); /* Addd IPv4 Address */ addrString = [[TRString alloc] initWithCString: "127.0.0.1"]; pfAddress = [[TRPFAddress alloc] initWithPresentationAddress: addrString]; fail_unless([pf addAddress: pfAddress toTable: name] == PF_SUCCESS); fail_unless([pf addressesFromTable: name withResult: &addresses] == PF_SUCCESS); fail_unless([addresses count] == 1, "Incorrect number of addresses. (expected 1, got %d)", [addresses count]); [addrString release]; [pfAddress release]; /* Test with IPv6 */ addrString = [[TRString alloc] initWithCString: "::1"]; pfAddress = [[TRPFAddress alloc] initWithPresentationAddress: addrString]; fail_unless([pf addAddress: pfAddress toTable: name] == PF_SUCCESS); fail_unless([pf addressesFromTable: name withResult: &addresses] == PF_SUCCESS); fail_unless([addresses count] == 2, "Incorrect number of addresses. (expected 2, got %d)", [addresses count]); [addrString release]; [pfAddress release]; [name release]; } END_TEST START_TEST(test_deleteAddressFromTable) { TRString *addrString; TRPFAddress *pfAddress; TRArray *addresses; TRString *name; name = [[TRString alloc] initWithCString: "ips_artist"]; fail_unless([pf flushTable: name] == PF_SUCCESS); /* Addd IPv4 Address */ addrString = [[TRString alloc] initWithCString: "127.0.0.1"]; pfAddress = [[TRPFAddress alloc] initWithPresentationAddress: addrString]; fail_unless([pf addAddress: pfAddress toTable: name] == PF_SUCCESS); fail_unless([pf addressesFromTable: name withResult: &addresses] == PF_SUCCESS); fail_unless([addresses count] == 1, "Incorrect number of addresses. (expected 1, got %d)", [addresses count]); fail_unless([pf deleteAddress: pfAddress fromTable: name] == PF_SUCCESS); fail_unless([pf addressesFromTable: name withResult: &addresses] == PF_SUCCESS); fail_unless([addresses count] == 0, "Incorrect number of addresses. (expected 0, got %d)", [addresses count]); [addrString release]; [pfAddress release]; [name release]; } END_TEST START_TEST(test_addressesFromTable) { TRString *addrString; TRPFAddress *pfAddress; TRArray *addresses; TRString *name; name = [[TRString alloc] initWithCString: "ips_artist"]; fail_unless([pf flushTable: name] == PF_SUCCESS); /* Addd IPv4 Address */ addrString = [[TRString alloc] initWithCString: "127.0.0.1"]; pfAddress = [[TRPFAddress alloc] initWithPresentationAddress: addrString]; fail_unless([pf addAddress: pfAddress toTable: name] == PF_SUCCESS); fail_unless([pf addressesFromTable: name withResult: &addresses] == PF_SUCCESS); fail_unless([addresses count] == 1, "Incorrect number of addresses. (expected 1, got %d)", [addresses count]); [addrString release]; [pfAddress release]; [name release]; } END_TEST Suite *TRLocalPacketFilter_suite(void) { Suite *s = suite_create("TRLocalPacketFilter"); TCase *tc_pf = tcase_create("PF Ioctl"); tcase_add_checked_fixture(tc_pf, setUp, tearDown); suite_add_tcase(s, tc_pf); tcase_add_test(tc_pf, test_init); tcase_add_test(tc_pf, test_tables); tcase_add_test(tc_pf, test_flushTable); tcase_add_test(tc_pf, test_addAddressToTable); tcase_add_test(tc_pf, test_deleteAddressFromTable); tcase_add_test(tc_pf, test_addressesFromTable); return s; } #endif /* HAVE_PF */ openvpn-auth-ldap-auth-ldap-2.0.4/tests/TRObjectTests.m000066400000000000000000000063121332642612100227550ustar00rootroot00000000000000/* * TRObject.m vi:ts=4:sw=4:expandtab: * TRObject Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * Copyright (c) 2007 - 2012 Landon Fuller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "TRObject.h" #import "PXTestCase.h" @interface TRObjectTests : PXTestCase @end @implementation TRObjectTests - (void) testIsKindOfClass { TRObject *trObj = [[[TRObject alloc] init] autorelease]; STAssertTrue([self isKindOfClass: [TRObject class]], "Test case should be considered a subclass of TRObject"); STAssertTrue([self isKindOfClass: [self class]], "Test case should consider itself to be of the same kind as its own class."); STAssertFalse([trObj isKindOfClass: [self class]], "TRObject is not an intance of TRObjectTests, or an instance of a TRObjectTests subclass"); } - (void) testRetainRelease { TRObject *obj; /* Initialize the object */ obj = [[TRObject alloc] init]; STAssertEquals([obj retainCount], (PXUInteger)1, "Newly initialized TRObject has unexpected reference count"); /* Increment the refcount */ [obj retain]; STAssertEquals([obj retainCount], (PXUInteger)2, "Retained TRObject has unexpected reference count"); /* Decrement the refcount */ [obj release]; STAssertEquals([obj retainCount], (PXUInteger)1, "Released TRObject has unexpected reference count"); /* Deallocate the object */ [obj release]; } - (void) testIsEqual { TRObject *obj; /* Initialize the object */ obj = [[TRObject alloc] init]; STAssertEqualObjects(obj, obj, "Object should be equal to self"); /* Deallocate the object */ [obj release]; } @end openvpn-auth-ldap-auth-ldap-2.0.4/tests/TRPFAddressTests.m000066400000000000000000000072761332642612100233740ustar00rootroot00000000000000/* * TRPPFAddress.m vi:ts=4:sw=4:expandtab: * TRPFAddress Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import #import "TRPFAddress.h" @interface TRPFAddressTests : PXTestCase @end @implementation TRPFAddressTests - (void) test_initWithPresentationAddress { TRString *addrString; TRPFAddress *pfAddr; /* Independent verification */ TRPortableAddress expected; TRPortableAddress actual; /* Test with IPv4 */ addrString = [[TRString alloc] initWithCString: "127.0.0.1"]; fail_unless(inet_pton(AF_INET, "127.0.0.1", &expected.ip4_addr)); pfAddr = [[TRPFAddress alloc] initWithPresentationAddress: addrString]; [addrString release]; /* Verify conversion */ fail_if(pfAddr == nil); [pfAddr address: &actual]; fail_unless(memcmp(&actual.ip4_addr, &expected.ip4_addr, sizeof(expected.ip4_addr)) == 0); [pfAddr release]; /* Test with IPv6 */ addrString = [[TRString alloc] initWithCString: "::1"]; fail_unless(inet_pton(AF_INET6, "::1", &expected.ip6_addr)); pfAddr = [[TRPFAddress alloc] initWithPresentationAddress: addrString]; [addrString release]; /* Verify conversion */ fail_if(pfAddr == nil); [pfAddr address: &actual]; fail_unless(memcmp(&actual.ip6_addr, &expected.ip6_addr, sizeof(expected.ip6_addr)) == 0); [pfAddr release]; } - (void) test_initWithPortableAddress { TRString *addrString; TRPFAddress *pfAddr; TRPortableAddress expected; TRPortableAddress actual; /* Initialize the source (expected) */ addrString = [[TRString alloc] initWithCString: "127.0.0.1"]; pfAddr = [[TRPFAddress alloc] initWithPresentationAddress: addrString]; fail_if(pfAddr == nil); [pfAddr address: &expected]; [addrString release]; [pfAddr release]; /* Initialize the dest (actual) */ pfAddr = [[TRPFAddress alloc] initWithPortableAddress: &expected]; fail_if(pfAddr == nil); [pfAddr address: &actual]; [pfAddr release]; /* Verify */ fail_unless(memcmp(&actual, &expected, sizeof(expected)) == 0); } @endopenvpn-auth-ldap-auth-ldap-2.0.4/tests/TRStringTests.m000066400000000000000000000140331332642612100230140ustar00rootroot00000000000000/* * TRString.m vi:ts=4:sw=4:expandtab: * TRString Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import "TRString.h" #import "TRAutoreleasePool.h" #import #import #define TEST_STRING "Hello, World!" @interface TRStringTests: PXTestCase @end @implementation TRStringTests - (void) test_initWithCString { const char *cString = TEST_STRING; TRString *str; str = [[TRString alloc] initWithCString: cString]; fail_if(str == NULL, "-[[TRString alloc] initWithCString:] returned NULL"); cString = [str cString]; fail_unless(strcmp(cString, TEST_STRING) == 0, "-[TRString cString] returned incorrect value. (Expected \"%s\", got \"%s\")", TEST_STRING, cString); [str release]; } - (void) test_initWithString { const char *cString = TEST_STRING; TRString *srcString = [[TRString alloc] initWithCString: cString]; TRString *str; str = [[TRString alloc] initWithString: srcString]; fail_if(str == NULL, "-[[TRString alloc] initWithString:] returned NULL"); cString = [str cString]; fail_unless(strcmp(cString, TEST_STRING) == 0, "-[TRString cString] returned incorrect value. (Expected \"%s\", got \"%s\")", TEST_STRING, cString); [srcString release]; [str release]; } - (void) test_initWithBytes { const char *data = TEST_STRING; const char *cString; TRString *str; /* Test with non-NULL terminated data */ str = [[TRString alloc] initWithBytes: data numBytes: sizeof(TEST_STRING) - 1]; fail_if(str == NULL, "-[[TRString alloc] initWithBytes:] returned NULL"); cString = [str cString]; fail_unless(strcmp(cString, TEST_STRING) == 0, "-[TRString cString] returned incorrect value. (Expected \"%s\", got \"%s\")", TEST_STRING, cString); [str release]; /* Test with NULL terminated data */ str = [[TRString alloc] initWithBytes: data numBytes: sizeof(TEST_STRING)]; fail_if(str == NULL, "-[[TRString alloc] initWithBytes:] returned NULL"); cString = [str cString]; fail_unless(strcmp(cString, TEST_STRING) == 0, "-[TRString cString] returned incorrect value. (Expected \"%s\", got \"%s\")", TEST_STRING, cString); [str release]; } - (void) test_stringWithFormat { TRAutoreleasePool *pool = [[TRAutoreleasePool alloc] init]; TRString *str; str = [TRString stringWithFormat: "%s %s", "Hello", "World"]; fail_unless(strcmp([str cString], "Hello World") == 0, "-[TRString cString] returned incorrect value. (Expected \"%s\", got \"%s\")", "Hello, World", [str cString]); [pool release]; } - (void) test_stringWithCString { TRAutoreleasePool *pool = [[TRAutoreleasePool alloc] init]; TRString *str; str = [TRString stringWithCString: "Hello World"]; fail_unless(strcmp([str cString], "Hello World") == 0, "-[TRString cString] returned incorrect value. (Expected \"%s\", got \"%s\")", "Hello, World", [str cString]); [pool release]; } - (void) test_length { TRString *str = [[TRString alloc] initWithCString: TEST_STRING]; size_t length = [str length]; fail_unless(length == sizeof(TEST_STRING), "-[TRString length] returned incorrect value. (Expected %u, got %u)", sizeof(TEST_STRING), length); [str release]; } - (void) test_intValue { TRString *str; int i; bool success; /* Test with integer */ str = [[TRString alloc] initWithCString: "20"]; success = [str intValue: &i]; fail_unless(success, "-[TRString intValue:] returned false"); fail_unless(i == 20, "-[TRString intValue:] returned incorrect value. (Expected %d, got %d)", 20, i); [str release]; /* Test with INT_MAX */ str = [[TRString alloc] initWithCString: "2147483647"]; success = [str intValue: &i]; fail_if(success, "-[LFstring intValue:] returned true for INT_MAX."); fail_unless(i == INT_MAX, "-[TRString intValue: returned incorrect value for INT_MAX. (Expected %d, got %d)", INT_MAX, i); [str release]; /* Test with INT_MIN */ str = [[TRString alloc] initWithCString: "-2147483648"]; success = [str intValue: &i]; fail_if(success, "-[LFstring intValue:] returned true for INT_MIN."); fail_unless(i == INT_MIN, "-[TRString intValue: returned incorrect value for INT_MIN. (Expected %d, got %d)", INT_MIN, i); [str release]; } - (void) test_hash { TRString *str = [[TRString alloc] initWithCString: TEST_STRING]; PXUInteger hash = [str hash]; fail_if(hash == 0); [str release]; } @endopenvpn-auth-ldap-auth-ldap-2.0.4/tests/TRVPNSessionTests.m000066400000000000000000000043301332642612100235540ustar00rootroot00000000000000/* * TRVPNSession.m vi:ts=4:sw=4:expandtab: * TRVPNSession Unit Tests * * Author: Landon Fuller * * Copyright (c) 2005 - 2007 Landon Fuller * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif #import "PXTestCase.h" #import "TRVPNSession.h" @interface TRVPNSessionTests : PXTestCase @end @implementation TRVPNSessionTests - (void) test_initWithUsername { TRVPNSession *session; TRString *username = [[TRString alloc] initWithCString: "user"]; session = [[TRVPNSession alloc] initWithUsername: username]; fail_unless([session username] == username); [username release]; [session release]; } @endopenvpn-auth-ldap-auth-ldap-2.0.4/tests/data/000077500000000000000000000000001332642612100210075ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/tests/data/TRConfig.conf000066400000000000000000000001571332642612100233340ustar00rootroot00000000000000 # LDAP server URL URI ldap://ldap1.example.org # Network timeout (in seconds) Timeout 15 openvpn-auth-ldap-auth-ldap-2.0.4/tests/data/auth-ldap-bad-section.conf000066400000000000000000000000751332642612100257250ustar00rootroot00000000000000# Contains an unknown section type openvpn-auth-ldap-auth-ldap-2.0.4/tests/data/auth-ldap-mismatched.conf000066400000000000000000000007101332642612100256470ustar00rootroot00000000000000 # LDAP server URL URL ldap://ldap1.example.org # Network timeout (in seconds) Timeout 15 # Enable TLS TLSEnable yes # TLS CA Certificate File TLSCACertFile /usr/local/etc/ssl/ca.pem # TLS CA Certificate Directory TLSCACertDir /etc/ssl/certs # Client Certificate TLSCertFile /usr/local/etc/ssl/client-cert.pem # Client Key TLSKeyFile /usr/local/etc/ssl/client-key.pem # Cipher Suite TLSCipherSuite ALL:!ADH:@STRENGTH openvpn-auth-ldap-auth-ldap-2.0.4/tests/data/auth-ldap-missing-newline.conf000066400000000000000000000020161332642612100266420ustar00rootroot00000000000000# A configuration that's missing the trailing newline. # Test for issue #8 # LDAP server URL URL ldap://ldap1.example.org # Bind DN (If your LDAP server doesn't support anonymous binds) BindDN uid=Manager,ou=People,dc=example,dc=com # Bind Password Password SuperSecretPassword # Network timeout (in seconds) Timeout 15 # Enable TLS TLSEnable yes # TLS CA Certificate File TLSCACertFile /usr/local/etc/ssl/ca.pem # TLS CA Certificate Directory TLSCACertDir /etc/ssl/certs # Client Certificate TLSCertFile /usr/local/etc/ssl/client-cert.pem # Client Key TLSKeyFile /usr/local/etc/ssl/client-key.pem # Cipher Suite TLSCipherSuite ALL:!ADH:@STRENGTH # Base DN BaseDN "ou=People,dc=example,dc=com" # User Search Filter SearchFilter "(&(uid=%u)(accountStatus=active))" # Require Group Membership RequireGroup false BaseDN "ou=Groups,dc=example,dc=com" SearchFilter "(|(cn=developers)(cn=artists))" MemberAttribute uniqueMember openvpn-auth-ldap-auth-ldap-2.0.4/tests/data/auth-ldap-multikey.conf000066400000000000000000000015101332642612100253730ustar00rootroot00000000000000 # LDAP server URL - Twice URL ldap://ldap1.example.org URL ldap://ldap1.example.org # Network timeout (in seconds) Timeout 15 # Enable TLS TLSEnable yes # TLS CA Certificate File TLSCACertFile /usr/local/etc/ssl/ca.pem # TLS CA Certificate Directory TLSCACertDir /etc/ssl/certs # Client Certificate TLSCertFile /usr/local/etc/ssl/client-cert.pem # Client Key TLSKeyFile /usr/local/etc/ssl/client-key.pem # Cipher Suite TLSCipherSuite ALL:!ADH:@STRENGTH # Base DN BaseDN "ou=People,dc=example,dc=com" # User Search Filter SearchFilter "(&(uid=%u)(accountStatus=active))" # Require Group Membership RequireGroup false BaseDN "ou=Groups,dc=example,dc=com" SearchFilter "(|(cn=developers)(cn=artists))" MemberAttribute uniqueMember openvpn-auth-ldap-auth-ldap-2.0.4/tests/data/auth-ldap-named.conf000066400000000000000000000006341332642612100246220ustar00rootroot00000000000000 # LDAP server URL URL ldap://ldap1.example.org # Network timeout (in seconds) Timeout 15 # Enable TLS TLSEnable yes # TLS CA Certificate File TLSCACertFile /usr/local/etc/ssl/ca.pem # TLS CA Certificate Directory #TLSCACertDir /etc/ssl/certs # Client Certificate #TLSCertFile /usr/local/etc/ssl/client-cert.pem # Client Key #TLSKeyFile /usr/local/etc/ssl/client-key.pem openvpn-auth-ldap-auth-ldap-2.0.4/tests/data/auth-ldap-pf.conf000066400000000000000000000020031332642612100241330ustar00rootroot00000000000000 # LDAP server URL URL ldap://ldap1.example.org # Bind DN (If your LDAP server doesn't support anonymous binds) BindDN uid=Manager,ou=People,dc=example,dc=com # Bind Password Password SuperSecretPassword # Network timeout (in seconds) Timeout 15 # Enable TLS TLSEnable yes # TLS CA Certificate File TLSCACertFile /usr/local/etc/ssl/ca.pem # TLS CA Certificate Directory TLSCACertDir /etc/ssl/certs # Client Certificate TLSCertFile /usr/local/etc/ssl/client-cert.pem # Client Key TLSKeyFile /usr/local/etc/ssl/client-key.pem # Cipher Suite TLSCipherSuite ALL:!ADH:@STRENGTH # Base DN BaseDN "ou=People,dc=example,dc=com" # User Search Filter SearchFilter "(&(uid=%u)(accountStatus=active))" # Require Group Membership RequireGroup false # Add to PF Table PFTable ips_users BaseDN "ou=Groups,dc=example,dc=com" SearchFilter "(|(cn=developers)(cn=artists))" MemberAttribute uniqueMember PFTable ips_trusted openvpn-auth-ldap-auth-ldap-2.0.4/tests/data/auth-ldap-required.conf000066400000000000000000000015041332642612100253530ustar00rootroot00000000000000 # LDAP server URL # Missing this required setting # URL ldap://ldap1.example.org # Network timeout (in seconds) Timeout 15 # Enable TLS TLSEnable yes # TLS CA Certificate File TLSCACertFile /usr/local/etc/ssl/ca.pem # TLS CA Certificate Directory TLSCACertDir /etc/ssl/certs # Client Certificate TLSCertFile /usr/local/etc/ssl/client-cert.pem # Client Key TLSKeyFile /usr/local/etc/ssl/client-key.pem # Cipher Suite TLSCipherSuite ALL:!ADH:@STRENGTH # Base DN BaseDN "ou=People,dc=example,dc=com" # User Search Filter SearchFilter "(&(uid=%u)(accountStatus=active))" # Require Group Membership RequireGroup false BaseDN "ou=Groups,dc=example,dc=com" SearchFilter "(|(cn=developers)(cn=artists))" MemberAttribute uniqueMember openvpn-auth-ldap-auth-ldap-2.0.4/tests/data/auth-ldap.conf000066400000000000000000000017041332642612100235370ustar00rootroot00000000000000 # LDAP server URL URL ldap://ldap1.example.org # Bind DN (If your LDAP server doesn't support anonymous binds) BindDN uid=Manager,ou=People,dc=example,dc=com # Bind Password Password SuperSecretPassword # Network timeout (in seconds) Timeout 15 # Enable TLS TLSEnable yes # TLS CA Certificate File TLSCACertFile /usr/local/etc/ssl/ca.pem # TLS CA Certificate Directory TLSCACertDir /etc/ssl/certs # Client Certificate TLSCertFile /usr/local/etc/ssl/client-cert.pem # Client Key TLSKeyFile /usr/local/etc/ssl/client-key.pem # Cipher Suite TLSCipherSuite ALL:!ADH:@STRENGTH # Base DN BaseDN "ou=People,dc=example,dc=com" # User Search Filter SearchFilter "(&(uid=%u)(accountStatus=active))" # Require Group Membership RequireGroup false BaseDN "ou=Groups,dc=example,dc=com" SearchFilter "(|(cn=developers)(cn=artists))" MemberAttribute uniqueMember openvpn-auth-ldap-auth-ldap-2.0.4/tests/data/test-lineNumbers.conf000066400000000000000000000002071332642612100251150ustar00rootroot00000000000000line 1 <2 2> line 3 # Comment # Comments line 6 line 7 line 8 line 9 <10 10> # Comment <11 11> line 13 line 15 openvpn-auth-ldap-auth-ldap-2.0.4/tests/mockpf.c000066400000000000000000000426261332642612100215330ustar00rootroot00000000000000/* * mockpf.c vi:ts=4:sw=4:expandtab: * Evil testing shim that captures pf ioctls and emulates * the /dev/pf interface. * * Author: Landon Fuller * * Portions of the validation code were taken from the pf kernel * implementation. * * Copyright (c) 2002 Cedric Berger * Copyright (c) 2006 - 2007 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #ifdef HAVE_PF #include #include #include #include #include #include #include #include #include #include #include #include #include /* * This code serves as a shim to allow the unit testing of /dev/pf * ioctl commands without providing root access or modifying the state * of the running system. Our functions tend towards assert() rather * than returning an error -- the point is to implode exactly where * an error is detected, allowing a client implementator to quickly find * the bug in their code. * * open() is hooked, and its path argument is matched against "/dev/pf". * If the path matches, /dev/null is instead opened, and the resultant * fd is saved as pffd. All future calls to open("/dev/pf",) will * reference this file descriptor. A reference count is maintained, * and close() is also hooked -- the file descriptor is actually closed * when the reference count reaches 0. * * Lastly, we hook ioctl(), and check for our pffd. If it's a pf(4) ioctl * command, we interpret the ioctl arguments directly -- implementing * a mock pf ioctl() interface. */ /* Retain a single (reference counted) file descriptor that will be used for * all pf(4) ioctls */ static int pffd = -1; static unsigned int pfRefCount = 0; /* Real function references */ static int (*_real_open)(const char *, int, ...) = NULL; static int (*_real_close)(int) = NULL; static int (*_real_ioctl)(int, unsigned long, ...) = NULL; /* Static example tables */ static struct pfr_table artist_table = { .pfrt_anchor = { '\0' }, .pfrt_name = "ips_artist", .pfrt_flags = 0, .pfrt_fback = 0 }; static struct pfr_table dev_table = { .pfrt_anchor = { '\0' }, .pfrt_name = "ips_developer", .pfrt_flags = 0, .pfrt_fback = 0 }; /** Generic structure definition for either list type. */ typedef struct PFNode { struct PFNode *prev; struct PFNode *next; } PFNode; /** Generic list structure. */ typedef struct PFList { unsigned int nodeCount; PFNode *firstNode; } PFList; /** Double linked list of addresses. */ typedef struct PFAddressNode { struct PFAddressNode *prev; struct PFAddressNode *next; struct pfr_addr addr; } PFAddressNode; /** Double linked list of tables. */ typedef struct PFTableNode { struct PFTableNode *prev; struct PFTableNode *next; struct pfr_table table; PFList addrs; } PFTableNode; static PFList *pf_tables; /** Initialize a new list. */ static void init_pflist(PFList *list) { list->firstNode = NULL; list->nodeCount = 0; } /** Initialize a new node. */ static void init_pfnode(PFNode *node) { node->prev = NULL; node->next = NULL; } /* Insert a node into the list */ static void insert_pfnode(PFList *list, PFNode *new, PFNode *position) { list->nodeCount++; /* Empty list */ if (!list->firstNode) { list->firstNode = new; return; } /* Top of list? */ if (!position) position = list->firstNode; new->prev = position->prev; new->next = position; if (position->prev) position->prev->next = new; else list->firstNode = new; position->prev = new; } /* Remove a node from a list */ static void remove_pfnode(PFList *list, PFNode *node) { list->nodeCount--; /* Last remaining node */ if (!node->prev && !node->next) { free(node); list->firstNode = NULL; return; } if (node->prev) node->prev->next = node->next; else list->firstNode = node->next; if (node->next) node->next->prev = node->prev; free(node); } /* Set up pf ioctl emulator */ void mockpf_setup(void) { PFTableNode *tableNode; pf_tables = malloc(sizeof(PFList)); init_pflist(pf_tables); /* Add our artist table */ tableNode = malloc(sizeof(PFTableNode)); init_pfnode((PFNode *) tableNode); init_pflist(&tableNode->addrs); tableNode->table = artist_table; insert_pfnode(pf_tables, (PFNode *) tableNode, NULL); /* Add our dev table */ tableNode = malloc(sizeof(PFTableNode)); init_pfnode((PFNode *) tableNode); tableNode->table = dev_table; init_pflist(&tableNode->addrs); insert_pfnode(pf_tables, (PFNode *) tableNode, NULL); } /* Tear down ioctl emulator */ void mockpf_teardown(void) { while (pf_tables->firstNode) { PFTableNode *tableNode = (PFTableNode *) pf_tables->firstNode; /* Clear out the address list */ while (tableNode->addrs.firstNode) remove_pfnode(&tableNode->addrs, tableNode->addrs.firstNode); remove_pfnode(pf_tables, pf_tables->firstNode); } free(pf_tables); } int open(const char *path, int flags, ...) { mode_t mode; va_list ap; /* Grab the real symbol if necessary */ if (!_real_open) _real_open = dlsym(RTLD_NEXT, "open"); /* Are we opening /dev/pf ? */ if(strcmp(path, PF_DEV_PATH) == 0) { /* Does a 'pf' reference already exist? */ if (pffd != -1) { pfRefCount++; return pffd; } else { pffd = _real_open("/dev/null", O_RDWR); /* Only increment the refcount if the open succeeded */ if (pffd != -1) pfRefCount++; return pffd; } } /* Call the real open */ if (flags & O_CREAT) { va_start(ap, flags); mode = va_arg(ap, int); va_end(ap); return _real_open(path, flags, mode); } else { return _real_open(path, flags); } } int close(int d) { int ret; /* Grab the real symbol if necessary */ if (!_real_close) _real_close = dlsym(RTLD_NEXT, "close"); if (d == pffd) { if (pfRefCount == 1) { ret = _real_close(pffd); /* Failure here is highly unlikely, but * we account for it anyway */ if (ret == -1) { return ret; } else { pfRefCount--; pffd = -1; } } } /* Call the real close */ return _real_close(d); } /** * Rewrite anchors referenced by tables to remove slashes and check for * validity. * Taken from FreeBSD: src/sys/contrib/pf/net/pf_table.c,v 1.7 */ int pfr_fix_anchor(char *anchor) { size_t siz = sizeof(((struct pfr_table *) NULL)->pfrt_anchor); int i; if (anchor[0] == '/') { char *path; int off; path = anchor; off = 1; while (*++path == '/') off++; bcopy(path, anchor, siz - off); memset(anchor + siz - off, 0, off); } assert(anchor[siz - 1] == 0); for (i = strlen(anchor); i < siz; i++) assert(!anchor[i]); return (0); } /** * Validate a table structure. * Taken from FreeBSD: src/sys/contrib/pf/net/pf_table.c,v 1.7 */ int pfr_validate_table(struct pfr_table *tbl) { int i; assert(tbl->pfrt_name[0]); assert(!tbl->pfrt_name[PF_TABLE_NAME_SIZE-1]); for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++) assert(!tbl->pfrt_name[i]); assert(pfr_fix_anchor(tbl->pfrt_anchor) == 0); assert(tbl->pfrt_flags == 0); return (1); } /** * Validate an address structure. * Taken from FreeBSD: src/sys/contrib/pf/net/pf_table.c,v 1.7 */ int pfr_validate_addr(struct pfr_addr *ad) { int i; assert(ad->pfra_af == AF_INET || ad->pfra_af == AF_INET6); switch (ad->pfra_af) { case AF_INET: assert(ad->pfra_net <= 32); break; case AF_INET6: assert(ad->pfra_net <= 128); break; default: /* Unreachable */ break; } if (ad->pfra_net < 128) assert(!(((caddr_t)ad)[ad->pfra_net/8] & (0xFF >> (ad->pfra_net%8)))); for (i = (ad->pfra_net+7)/8; i < sizeof(ad->pfra_u); i++) assert(!((caddr_t)ad)[i]); if (ad->pfra_not) assert(ad->pfra_not == 1); assert(!ad->pfra_fback); return (1); } int ioctl(int d, unsigned long request, ...) { va_list ap; caddr_t argp; /* Grab the real symbol if necessary */ if (!_real_ioctl) _real_ioctl = dlsym(RTLD_NEXT, "ioctl"); /* Fish out the argument */ va_start(ap, request); argp = va_arg(ap, caddr_t); va_end(ap); if (d == pffd) { switch (request) { struct pfioc_table *iot; struct pfr_table *table; struct pfr_addr *address; PFTableNode *tableNode; PFAddressNode *addressNode; int size; case DIOCRGETTABLES: iot = (struct pfioc_table *) argp; /* Verify structure initialization */ assert(iot->pfrio_esize == sizeof(struct pfr_table)); /* Check our caller's buffer size */ size = sizeof(struct pfr_table) * pf_tables->nodeCount; if (iot->pfrio_size < size) { iot->pfrio_size = size; return 0; } else { iot->pfrio_size = size; } table = iot->pfrio_buffer; for (tableNode = (PFTableNode *) pf_tables->firstNode; tableNode != NULL; tableNode = tableNode->next) { memcpy(table, &tableNode->table, sizeof(struct pfr_table)); table++; } return 0; case DIOCRCLRADDRS: iot = (struct pfioc_table *) argp; /* Verify structure initialization */ assert(iot->pfrio_esize == 0); /* Find the table */ size = 0; /* Number of addresses cleared */ for (tableNode = (PFTableNode *) pf_tables->firstNode; tableNode != NULL; tableNode = tableNode->next) { /* Check the name */ if (strcmp(iot->pfrio_table.pfrt_name, tableNode->table.pfrt_name) == 0) { /* Matched. Clear out the address list */ while (tableNode->addrs.firstNode) { remove_pfnode(&tableNode->addrs, tableNode->addrs.firstNode); size++; } iot->pfrio_ndel = size; return 0; } } /* If we fall through the table wasn't found */ errno = ESRCH; return -1; case DIOCRADDADDRS: iot = (struct pfioc_table *) argp; /* Verify structure initialization */ assert(iot->pfrio_esize == sizeof(struct pfr_addr)); /* Validate table */ assert(pfr_validate_table (&iot->pfrio_table)); /* Find the table */ size = 0; /* Number of addresses added */ for (tableNode = (PFTableNode *) pf_tables->firstNode; tableNode != NULL; tableNode = tableNode->next) { int i, max; /* Check the name */ if (strcmp(iot->pfrio_table.pfrt_name, tableNode->table.pfrt_name) == 0) { /* Matched. Add the addresses */ address = iot->pfrio_buffer; max = iot->pfrio_size; for (i = 0; i < max; i++) { assert(pfr_validate_addr(address)); addressNode = malloc(sizeof(PFAddressNode)); init_pfnode((PFNode *) addressNode); memcpy(&addressNode->addr, address, sizeof(addressNode->addr)); insert_pfnode(&tableNode->addrs, (PFNode *) addressNode, NULL); address++; size++; } /* Number of addresses added */ iot->pfrio_nadd = size; return 0; } } /* If we fall through the table wasn't found */ errno = ESRCH; return -1; case DIOCRDELADDRS: iot = (struct pfioc_table *) argp; /* Verify structure initialization */ assert(iot->pfrio_esize == sizeof(struct pfr_addr)); /* Validate table */ pfr_validate_table (&iot->pfrio_table); /* Find the table */ size = 0; /* Number of addresses deleted */ for (tableNode = (PFTableNode *) pf_tables->firstNode; tableNode != NULL; tableNode = tableNode->next) { int i, max; /* Check the name */ if (strcmp(iot->pfrio_table.pfrt_name, tableNode->table.pfrt_name) == 0) { /* Matched the table. Delete the addresses */ address = iot->pfrio_buffer; max = iot->pfrio_size; for (i = 0; i < max; i++) { int addrMatch = 0; assert(pfr_validate_addr(address)); for (addressNode = (PFAddressNode *) tableNode->addrs.firstNode; addressNode != NULL; addressNode = addressNode->next) { if (memcmp(&addressNode->addr, address, sizeof(addressNode->addr)) == 0) { /* Matched the address */ addrMatch = 1; remove_pfnode(&tableNode->addrs, (PFNode *) addressNode); size++; break; } } address++; } /* Number of addresses deleted */ iot->pfrio_ndel = size; return 0; } } /* If we fall through the table wasn't found */ errno = ESRCH; return -1; case DIOCRGETADDRS: iot = (struct pfioc_table *) argp; /* Verify structure initialization */ assert(iot->pfrio_esize == sizeof(struct pfr_addr)); /* Find the table */ for (tableNode = (PFTableNode *) pf_tables->firstNode; tableNode != NULL; tableNode = tableNode->next) { /* Check the name */ if (strcmp(iot->pfrio_table.pfrt_name, tableNode->table.pfrt_name) == 0) { /* Matched. Check our caller's buffer size */ size = tableNode->addrs.nodeCount; if (iot->pfrio_size < size) { iot->pfrio_size = size; return 0; } else { iot->pfrio_size = size; } address = iot->pfrio_buffer; for (addressNode = (PFAddressNode *) tableNode->addrs.firstNode; addressNode != NULL; addressNode = addressNode->next) { memcpy(address, &addressNode->addr, sizeof(struct pfr_addr)); address++; } return 0; } } /* If we fall through the table wasn't found */ errno = ESRCH; return -1; default: errno = EINVAL; return -1; } } /* Call the real ioctl */ return (_real_ioctl(d, request, argp)); } #endif /* HAVE_PF */ openvpn-auth-ldap-auth-ldap-2.0.4/tests/mockpf.h000066400000000000000000000033421332642612100215300ustar00rootroot00000000000000/* * mockpf.h vi:ts=4:sw=4:expandtab: * Evil testing shim that captures pf ioctls and emulates * the /dev/pf interface. * * Author: Landon Fuller * * Portions of the validation code were taken from the pf kernel * implementation. * * Copyright (c) 2002 Cedric Berger * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ void mockpf_setup(void); void mockpf_teardown(void); openvpn-auth-ldap-auth-ldap-2.0.4/tests/tests.h000066400000000000000000000047601332642612100214200ustar00rootroot00000000000000/* * tests.h vi:ts=4:sw=4:expandtab: * OpenVPN LDAP Authentication Plugin Unit Tests * * Author: Landon Fuller * * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #import #endif /* * Useful Paths */ #ifndef TEST_DATA #error Path to test data must be supplied at compile time. #endif #define DATA_PATH(relative) TEST_DATA "/" relative #ifndef HAVE_PF #define AUTH_LDAP_CONF DATA_PATH("auth-ldap.conf") #else #define AUTH_LDAP_CONF DATA_PATH("auth-ldap-pf.conf") #endif /* HAVE_PF */ #define AUTH_LDAP_CONF_NAMED DATA_PATH("auth-ldap-named.conf") #define AUTH_LDAP_CONF_MISMATCHED DATA_PATH("auth-ldap-mismatched.conf") #define AUTH_LDAP_CONF_MULTIKEY DATA_PATH("auth-ldap-multikey.conf") #define AUTH_LDAP_CONF_REQUIRED DATA_PATH("auth-ldap-required.conf") #define AUTH_LDAP_CONF_MISSING_NEWLINE DATA_PATH("auth-ldap-missing-newline.conf") #define AUTH_LDAP_CONF_BAD_SECTION DATA_PATH("auth-ldap-bad-section.conf") openvpn-auth-ldap-auth-ldap-2.0.4/tests/tests.m000066400000000000000000000053201332642612100214160ustar00rootroot00000000000000/* * tests.c vi:ts=4:sw=4:expandtab: * OpenVPN LDAP Authentication Plugin Unit Tests * * Author: Landon Fuller * * Copyright (c) 2005 Landon Fuller * Copyright (c) 2006 Three Rings Design, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Landon Fuller nor the names of any contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ #import #import #import #import "TRLog.h" #import "TRAutoreleasePool.h" #import "PXTestCaseRunner.h" #import "PXTestConsoleResultHandler.h" void print_usage(const char *name) { printf("Usage: %s [filename]\n", name); printf(" [filename]\tWrite XML log to \n"); } int main(int argc, char *argv[]) { TRAutoreleasePool *pool = [[TRAutoreleasePool alloc] init]; /* Set up the test runner and reporting. */ PXTestConsoleResultHandler *handler = [[[PXTestConsoleResultHandler alloc] init] autorelease]; PXTestCaseRunner *runner = [[[PXTestCaseRunner alloc] initWithResultHandler: handler] autorelease]; /* Run tests */ [TRLog _quiesceLogging: YES]; BOOL success = [runner runAllCases]; [TRLog _quiesceLogging: NO]; [pool release]; if (success) { exit(EXIT_SUCCESS); } else { exit(EXIT_FAILURE); } } openvpn-auth-ldap-auth-ldap-2.0.4/tools/000077500000000000000000000000001332642612100200745ustar00rootroot00000000000000openvpn-auth-ldap-auth-ldap-2.0.4/tools/Makefile.in000077500000000000000000000011531332642612100221440ustar00rootroot00000000000000srcdir= @srcdir@ top_srcdir= @top_srcdir@ top_builddir= @top_builddir@ VPATH= @srcdir@ include ${top_builddir}/Mk/autoconf.mk include ${top_builddir}/Mk/compile.mk include ${top_builddir}/Mk/subdir.mk # Build the Lemon tool LEMON_OBJS= lemon.o MAKEHEADERS_OBJS= makeheaders.o CFLAGS= all:: lemon makeheaders lemon: $(LEMON_OBJS) $(CC) ${CFLAGS} -o $@ $(LEMON_OBJS) $(LIBS) $(LDFLAGS) makeheaders: $(MAKEHEADERS_OBJS) $(CC) ${CFLAGS} -o $@ $(MAKEHEADERS_OBJS) $(LIBS) $(LDFLAGS) clean:: rm -f $(LEMON_OBJS) lemon rm -f $(MAKEHEADERS_OBJS) makeheaders distclean:: clean rm -f Makefile openvpn-auth-ldap-auth-ldap-2.0.4/tools/README000066400000000000000000000010101332642612100207440ustar00rootroot00000000000000This directory contains tools required to build the OpenVPN Auth-LDAP Plugin: - lemon 2012-01-14 was downloaded from http://www.hwaci.com/sw/lemon/ The Lemon tool was modified as follows: - Write output to the defined -O path. - Added missing include to the lempar.c template. - Include stdio.h in headers generated by makeheaders - makeheaders was downloaded from http://www.hwaci.com/sw/mkhdr/ The makeheaders tool was modified to treat Objective-C source files (.m) as C files. openvpn-auth-ldap-auth-ldap-2.0.4/tools/lemon.c000066400000000000000000004377171332642612100213750ustar00rootroot00000000000000/* ** This file contains all sources (including headers) to the LEMON ** LALR(1) parser generator. The sources have been combined into a ** single file to make it easy to include LEMON in the source tree ** and Makefile of another program. ** ** The author of this program disclaims copyright. */ #include #include #include #include #include #include #ifndef __WIN32__ # if defined(_WIN32) || defined(WIN32) # define __WIN32__ # endif #endif #ifdef __WIN32__ #ifdef __cplusplus extern "C" { #endif extern int access(const char *path, int mode); #ifdef __cplusplus } #endif #else #include #endif /* #define PRIVATE static */ #define PRIVATE #ifdef TEST #define MAXRHS 5 /* Set low to exercise exception code */ #else #define MAXRHS 1000 #endif static int showPrecedenceConflict = 0; static char *msort(char*,char**,int(*)(const char*,const char*)); /* ** Compilers are getting increasingly pedantic about type conversions ** as C evolves ever closer to Ada.... To work around the latest problems ** we have to define the following variant of strlen(). */ #define lemonStrlen(X) ((int)strlen(X)) /* a few forward declarations... */ struct rule; struct lemon; struct action; static struct action *Action_new(void); static struct action *Action_sort(struct action *); /********** From the file "build.h" ************************************/ void FindRulePrecedences(); void FindFirstSets(); void FindStates(); void FindLinks(); void FindFollowSets(); void FindActions(); /********* From the file "configlist.h" *********************************/ void Configlist_init(void); struct config *Configlist_add(struct rule *, int); struct config *Configlist_addbasis(struct rule *, int); void Configlist_closure(struct lemon *); void Configlist_sort(void); void Configlist_sortbasis(void); struct config *Configlist_return(void); struct config *Configlist_basis(void); void Configlist_eat(struct config *); void Configlist_reset(void); /********* From the file "error.h" ***************************************/ void ErrorMsg(const char *, int,const char *, ...); /****** From the file "option.h" ******************************************/ enum option_type { OPT_FLAG=1, OPT_INT, OPT_DBL, OPT_STR, OPT_FFLAG, OPT_FINT, OPT_FDBL, OPT_FSTR}; struct s_options { enum option_type type; const char *label; char *arg; const char *message; }; int OptInit(char**,struct s_options*,FILE*); int OptNArgs(void); char *OptArg(int); void OptErr(int); void OptPrint(void); /******** From the file "parse.h" *****************************************/ void Parse(struct lemon *lemp); /********* From the file "plink.h" ***************************************/ struct plink *Plink_new(void); void Plink_add(struct plink **, struct config *); void Plink_copy(struct plink **, struct plink *); void Plink_delete(struct plink *); /********** From the file "report.h" *************************************/ void Reprint(struct lemon *); void ReportOutput(struct lemon *); void ReportTable(struct lemon *, int); void ReportHeader(struct lemon *); void CompressTables(struct lemon *); void ResortStates(struct lemon *); /********** From the file "set.h" ****************************************/ void SetSize(int); /* All sets will be of size N */ char *SetNew(void); /* A new set for element 0..N */ void SetFree(char*); /* Deallocate a set */ int SetAdd(char*,int); /* Add element to a set */ int SetUnion(char *,char *); /* A <- A U B, thru element N */ #define SetFind(X,Y) (X[Y]) /* True if Y is in set X */ /********** From the file "struct.h" *************************************/ /* ** Principal data structures for the LEMON parser generator. */ typedef enum {LEMON_FALSE=0, LEMON_TRUE} Boolean; /* Symbols (terminals and nonterminals) of the grammar are stored ** in the following: */ enum symbol_type { TERMINAL, NONTERMINAL, MULTITERMINAL }; enum e_assoc { LEFT, RIGHT, NONE, UNK }; struct symbol { const char *name; /* Name of the symbol */ int index; /* Index number for this symbol */ enum symbol_type type; /* Symbols are all either TERMINALS or NTs */ struct rule *rule; /* Linked list of rules of this (if an NT) */ struct symbol *fallback; /* fallback token in case this token doesn't parse */ int prec; /* Precedence if defined (-1 otherwise) */ enum e_assoc assoc; /* Associativity if precedence is defined */ char *firstset; /* First-set for all rules of this symbol */ Boolean lambda; /* True if NT and can generate an empty string */ int useCnt; /* Number of times used */ char *destructor; /* Code which executes whenever this symbol is ** popped from the stack during error processing */ int destLineno; /* Line number for start of destructor */ char *datatype; /* The data type of information held by this ** object. Only used if type==NONTERMINAL */ int dtnum; /* The data type number. In the parser, the value ** stack is a union. The .yy%d element of this ** union is the correct data type for this object */ /* The following fields are used by MULTITERMINALs only */ int nsubsym; /* Number of constituent symbols in the MULTI */ struct symbol **subsym; /* Array of constituent symbols */ }; /* Each production rule in the grammar is stored in the following ** structure. */ struct rule { struct symbol *lhs; /* Left-hand side of the rule */ const char *lhsalias; /* Alias for the LHS (NULL if none) */ int lhsStart; /* True if left-hand side is the start symbol */ int ruleline; /* Line number for the rule */ int nrhs; /* Number of RHS symbols */ struct symbol **rhs; /* The RHS symbols */ const char **rhsalias; /* An alias for each RHS symbol (NULL if none) */ int line; /* Line number at which code begins */ const char *code; /* The code executed when this rule is reduced */ struct symbol *precsym; /* Precedence symbol for this rule */ int index; /* An index number for this rule */ Boolean canReduce; /* True if this rule is ever reduced */ struct rule *nextlhs; /* Next rule with the same LHS */ struct rule *next; /* Next rule in the global list */ }; /* A configuration is a production rule of the grammar together with ** a mark (dot) showing how much of that rule has been processed so far. ** Configurations also contain a follow-set which is a list of terminal ** symbols which are allowed to immediately follow the end of the rule. ** Every configuration is recorded as an instance of the following: */ enum cfgstatus { COMPLETE, INCOMPLETE }; struct config { struct rule *rp; /* The rule upon which the configuration is based */ int dot; /* The parse point */ char *fws; /* Follow-set for this configuration only */ struct plink *fplp; /* Follow-set forward propagation links */ struct plink *bplp; /* Follow-set backwards propagation links */ struct state *stp; /* Pointer to state which contains this */ enum cfgstatus status; /* used during followset and shift computations */ struct config *next; /* Next configuration in the state */ struct config *bp; /* The next basis configuration */ }; enum e_action { SHIFT, ACCEPT, REDUCE, ERROR, SSCONFLICT, /* A shift/shift conflict */ SRCONFLICT, /* Was a reduce, but part of a conflict */ RRCONFLICT, /* Was a reduce, but part of a conflict */ SH_RESOLVED, /* Was a shift. Precedence resolved conflict */ RD_RESOLVED, /* Was reduce. Precedence resolved conflict */ NOT_USED /* Deleted by compression */ }; /* Every shift or reduce operation is stored as one of the following */ struct action { struct symbol *sp; /* The look-ahead symbol */ enum e_action type; union { struct state *stp; /* The new state, if a shift */ struct rule *rp; /* The rule, if a reduce */ } x; struct action *next; /* Next action for this state */ struct action *collide; /* Next action with the same hash */ }; /* Each state of the generated parser's finite state machine ** is encoded as an instance of the following structure. */ struct state { struct config *bp; /* The basis configurations for this state */ struct config *cfp; /* All configurations in this set */ int statenum; /* Sequential number for this state */ struct action *ap; /* Array of actions for this state */ int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */ int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */ int iDflt; /* Default action */ }; #define NO_OFFSET (-2147483647) /* A followset propagation link indicates that the contents of one ** configuration followset should be propagated to another whenever ** the first changes. */ struct plink { struct config *cfp; /* The configuration to which linked */ struct plink *next; /* The next propagate link */ }; /* The state vector for the entire parser generator is recorded as ** follows. (LEMON uses no global variables and makes little use of ** static variables. Fields in the following structure can be thought ** of as begin global variables in the program.) */ struct lemon { struct state **sorted; /* Table of states sorted by state number */ struct rule *rule; /* List of all rules */ int nstate; /* Number of states */ int nrule; /* Number of rules */ int nsymbol; /* Number of terminal and nonterminal symbols */ int nterminal; /* Number of terminal symbols */ struct symbol **symbols; /* Sorted array of pointers to symbols */ int errorcnt; /* Number of errors */ struct symbol *errsym; /* The error symbol */ struct symbol *wildcard; /* Token that matches anything */ char *name; /* Name of the generated parser */ char *arg; /* Declaration of the 3th argument to parser */ char *tokentype; /* Type of terminal symbols in the parser stack */ char *vartype; /* The default type of non-terminal symbols */ char *start; /* Name of the start symbol for the grammar */ char *stacksize; /* Size of the parser stack */ char *include; /* Code to put at the start of the C file */ char *error; /* Code to execute when an error is seen */ char *overflow; /* Code to execute on a stack overflow */ char *failure; /* Code to execute on parser failure */ char *accept; /* Code to execute when the parser excepts */ char *extracode; /* Code appended to the generated file */ char *tokendest; /* Code to execute to destroy token data */ char *vardest; /* Code for the default non-terminal destructor */ char *filename; /* Name of the input file */ char *outname; /* Name of the current output file */ char *tokenprefix; /* A prefix added to token names in the .h file */ int nconflict; /* Number of parsing conflicts */ int tablesize; /* Size of the parse tables */ int basisflag; /* Print only basis configurations */ int has_fallback; /* True if any %fallback is seen in the grammar */ int nolinenosflag; /* True if #line statements should not be printed */ char *argv0; /* Name of the program */ }; #define MemoryCheck(X) if((X)==0){ \ extern void memory_error(); \ memory_error(); \ } /**************** From the file "table.h" *********************************/ /* ** All code in this file has been automatically generated ** from a specification in the file ** "table.q" ** by the associative array code building program "aagen". ** Do not edit this file! Instead, edit the specification ** file, then rerun aagen. */ /* ** Code for processing tables in the LEMON parser generator. */ /* Routines for handling a strings */ const char *Strsafe(const char *); void Strsafe_init(void); int Strsafe_insert(const char *); const char *Strsafe_find(const char *); /* Routines for handling symbols of the grammar */ struct symbol *Symbol_new(const char *); int Symbolcmpp(const void *, const void *); void Symbol_init(void); int Symbol_insert(struct symbol *, const char *); struct symbol *Symbol_find(const char *); struct symbol *Symbol_Nth(int); int Symbol_count(void); struct symbol **Symbol_arrayof(void); /* Routines to manage the state table */ int Configcmp(const char *, const char *); struct state *State_new(void); void State_init(void); int State_insert(struct state *, struct config *); struct state *State_find(struct config *); struct state **State_arrayof(/* */); /* Routines used for efficiency in Configlist_add */ void Configtable_init(void); int Configtable_insert(struct config *); struct config *Configtable_find(struct config *); void Configtable_clear(int(*)(struct config *)); /****************** From the file "action.c" *******************************/ /* ** Routines processing parser actions in the LEMON parser generator. */ /* Allocate a new parser action */ static struct action *Action_new(void){ static struct action *freelist = 0; struct action *newaction; if( freelist==0 ){ int i; int amt = 100; freelist = (struct action *)calloc(amt, sizeof(struct action)); if( freelist==0 ){ fprintf(stderr,"Unable to allocate memory for a new parser action."); exit(1); } for(i=0; inext; return newaction; } /* Compare two actions for sorting purposes. Return negative, zero, or ** positive if the first action is less than, equal to, or greater than ** the first */ static int actioncmp( struct action *ap1, struct action *ap2 ){ int rc; rc = ap1->sp->index - ap2->sp->index; if( rc==0 ){ rc = (int)ap1->type - (int)ap2->type; } if( rc==0 && ap1->type==REDUCE ){ rc = ap1->x.rp->index - ap2->x.rp->index; } if( rc==0 ){ rc = (int) (ap2 - ap1); } return rc; } /* Sort parser actions */ static struct action *Action_sort( struct action *ap ){ ap = (struct action *)msort((char *)ap,(char **)&ap->next, (int(*)(const char*,const char*))actioncmp); return ap; } void Action_add( struct action **app, enum e_action type, struct symbol *sp, char *arg ){ struct action *newaction; newaction = Action_new(); newaction->next = *app; *app = newaction; newaction->type = type; newaction->sp = sp; if( type==SHIFT ){ newaction->x.stp = (struct state *)arg; }else{ newaction->x.rp = (struct rule *)arg; } } /********************** New code to implement the "acttab" module ***********/ /* ** This module implements routines use to construct the yy_action[] table. */ /* ** The state of the yy_action table under construction is an instance of ** the following structure. ** ** The yy_action table maps the pair (state_number, lookahead) into an ** action_number. The table is an array of integers pairs. The state_number ** determines an initial offset into the yy_action array. The lookahead ** value is then added to this initial offset to get an index X into the ** yy_action array. If the aAction[X].lookahead equals the value of the ** of the lookahead input, then the value of the action_number output is ** aAction[X].action. If the lookaheads do not match then the ** default action for the state_number is returned. ** ** All actions associated with a single state_number are first entered ** into aLookahead[] using multiple calls to acttab_action(). Then the ** actions for that single state_number are placed into the aAction[] ** array with a single call to acttab_insert(). The acttab_insert() call ** also resets the aLookahead[] array in preparation for the next ** state number. */ struct lookahead_action { int lookahead; /* Value of the lookahead token */ int action; /* Action to take on the given lookahead */ }; typedef struct acttab acttab; struct acttab { int nAction; /* Number of used slots in aAction[] */ int nActionAlloc; /* Slots allocated for aAction[] */ struct lookahead_action *aAction, /* The yy_action[] table under construction */ *aLookahead; /* A single new transaction set */ int mnLookahead; /* Minimum aLookahead[].lookahead */ int mnAction; /* Action associated with mnLookahead */ int mxLookahead; /* Maximum aLookahead[].lookahead */ int nLookahead; /* Used slots in aLookahead[] */ int nLookaheadAlloc; /* Slots allocated in aLookahead[] */ }; /* Return the number of entries in the yy_action table */ #define acttab_size(X) ((X)->nAction) /* The value for the N-th entry in yy_action */ #define acttab_yyaction(X,N) ((X)->aAction[N].action) /* The value for the N-th entry in yy_lookahead */ #define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead) /* Free all memory associated with the given acttab */ void acttab_free(acttab *p){ free( p->aAction ); free( p->aLookahead ); free( p ); } /* Allocate a new acttab structure */ acttab *acttab_alloc(void){ acttab *p = (acttab *) calloc( 1, sizeof(*p) ); if( p==0 ){ fprintf(stderr,"Unable to allocate memory for a new acttab."); exit(1); } memset(p, 0, sizeof(*p)); return p; } /* Add a new action to the current transaction set. ** ** This routine is called once for each lookahead for a particular ** state. */ void acttab_action(acttab *p, int lookahead, int action){ if( p->nLookahead>=p->nLookaheadAlloc ){ p->nLookaheadAlloc += 25; p->aLookahead = (struct lookahead_action *) realloc( p->aLookahead, sizeof(p->aLookahead[0])*p->nLookaheadAlloc ); if( p->aLookahead==0 ){ fprintf(stderr,"malloc failed\n"); exit(1); } } if( p->nLookahead==0 ){ p->mxLookahead = lookahead; p->mnLookahead = lookahead; p->mnAction = action; }else{ if( p->mxLookaheadmxLookahead = lookahead; if( p->mnLookahead>lookahead ){ p->mnLookahead = lookahead; p->mnAction = action; } } p->aLookahead[p->nLookahead].lookahead = lookahead; p->aLookahead[p->nLookahead].action = action; p->nLookahead++; } /* ** Add the transaction set built up with prior calls to acttab_action() ** into the current action table. Then reset the transaction set back ** to an empty set in preparation for a new round of acttab_action() calls. ** ** Return the offset into the action table of the new transaction. */ int acttab_insert(acttab *p){ int i, j, k, n; assert( p->nLookahead>0 ); /* Make sure we have enough space to hold the expanded action table ** in the worst case. The worst case occurs if the transaction set ** must be appended to the current action table */ n = p->mxLookahead + 1; if( p->nAction + n >= p->nActionAlloc ){ int oldAlloc = p->nActionAlloc; p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20; p->aAction = (struct lookahead_action *) realloc( p->aAction, sizeof(p->aAction[0])*p->nActionAlloc); if( p->aAction==0 ){ fprintf(stderr,"malloc failed\n"); exit(1); } for(i=oldAlloc; inActionAlloc; i++){ p->aAction[i].lookahead = -1; p->aAction[i].action = -1; } } /* Scan the existing action table looking for an offset that is a ** duplicate of the current transaction set. Fall out of the loop ** if and when the duplicate is found. ** ** i is the index in p->aAction[] where p->mnLookahead is inserted. */ for(i=p->nAction-1; i>=0; i--){ if( p->aAction[i].lookahead==p->mnLookahead ){ /* All lookaheads and actions in the aLookahead[] transaction ** must match against the candidate aAction[i] entry. */ if( p->aAction[i].action!=p->mnAction ) continue; for(j=0; jnLookahead; j++){ k = p->aLookahead[j].lookahead - p->mnLookahead + i; if( k<0 || k>=p->nAction ) break; if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break; if( p->aLookahead[j].action!=p->aAction[k].action ) break; } if( jnLookahead ) continue; /* No possible lookahead value that is not in the aLookahead[] ** transaction is allowed to match aAction[i] */ n = 0; for(j=0; jnAction; j++){ if( p->aAction[j].lookahead<0 ) continue; if( p->aAction[j].lookahead==j+p->mnLookahead-i ) n++; } if( n==p->nLookahead ){ break; /* An exact match is found at offset i */ } } } /* If no existing offsets exactly match the current transaction, find an ** an empty offset in the aAction[] table in which we can add the ** aLookahead[] transaction. */ if( i<0 ){ /* Look for holes in the aAction[] table that fit the current ** aLookahead[] transaction. Leave i set to the offset of the hole. ** If no holes are found, i is left at p->nAction, which means the ** transaction will be appended. */ for(i=0; inActionAlloc - p->mxLookahead; i++){ if( p->aAction[i].lookahead<0 ){ for(j=0; jnLookahead; j++){ k = p->aLookahead[j].lookahead - p->mnLookahead + i; if( k<0 ) break; if( p->aAction[k].lookahead>=0 ) break; } if( jnLookahead ) continue; for(j=0; jnAction; j++){ if( p->aAction[j].lookahead==j+p->mnLookahead-i ) break; } if( j==p->nAction ){ break; /* Fits in empty slots */ } } } } /* Insert transaction set at index i. */ for(j=0; jnLookahead; j++){ k = p->aLookahead[j].lookahead - p->mnLookahead + i; p->aAction[k] = p->aLookahead[j]; if( k>=p->nAction ) p->nAction = k+1; } p->nLookahead = 0; /* Return the offset that is added to the lookahead in order to get the ** index into yy_action of the action */ return i - p->mnLookahead; } /********************** From the file "build.c" *****************************/ /* ** Routines to construction the finite state machine for the LEMON ** parser generator. */ /* Find a precedence symbol of every rule in the grammar. ** ** Those rules which have a precedence symbol coded in the input ** grammar using the "[symbol]" construct will already have the ** rp->precsym field filled. Other rules take as their precedence ** symbol the first RHS symbol with a defined precedence. If there ** are not RHS symbols with a defined precedence, the precedence ** symbol field is left blank. */ void FindRulePrecedences(struct lemon *xp) { struct rule *rp; for(rp=xp->rule; rp; rp=rp->next){ if( rp->precsym==0 ){ int i, j; for(i=0; inrhs && rp->precsym==0; i++){ struct symbol *sp = rp->rhs[i]; if( sp->type==MULTITERMINAL ){ for(j=0; jnsubsym; j++){ if( sp->subsym[j]->prec>=0 ){ rp->precsym = sp->subsym[j]; break; } } }else if( sp->prec>=0 ){ rp->precsym = rp->rhs[i]; } } } } return; } /* Find all nonterminals which will generate the empty string. ** Then go back and compute the first sets of every nonterminal. ** The first set is the set of all terminal symbols which can begin ** a string generated by that nonterminal. */ void FindFirstSets(struct lemon *lemp) { int i, j; struct rule *rp; int progress; for(i=0; insymbol; i++){ lemp->symbols[i]->lambda = LEMON_FALSE; } for(i=lemp->nterminal; insymbol; i++){ lemp->symbols[i]->firstset = SetNew(); } /* First compute all lambdas */ do{ progress = 0; for(rp=lemp->rule; rp; rp=rp->next){ if( rp->lhs->lambda ) continue; for(i=0; inrhs; i++){ struct symbol *sp = rp->rhs[i]; assert( sp->type==NONTERMINAL || sp->lambda==LEMON_FALSE ); if( sp->lambda==LEMON_FALSE ) break; } if( i==rp->nrhs ){ rp->lhs->lambda = LEMON_TRUE; progress = 1; } } }while( progress ); /* Now compute all first sets */ do{ struct symbol *s1, *s2; progress = 0; for(rp=lemp->rule; rp; rp=rp->next){ s1 = rp->lhs; for(i=0; inrhs; i++){ s2 = rp->rhs[i]; if( s2->type==TERMINAL ){ progress += SetAdd(s1->firstset,s2->index); break; }else if( s2->type==MULTITERMINAL ){ for(j=0; jnsubsym; j++){ progress += SetAdd(s1->firstset,s2->subsym[j]->index); } break; }else if( s1==s2 ){ if( s1->lambda==LEMON_FALSE ) break; }else{ progress += SetUnion(s1->firstset,s2->firstset); if( s2->lambda==LEMON_FALSE ) break; } } } }while( progress ); return; } /* Compute all LR(0) states for the grammar. Links ** are added to between some states so that the LR(1) follow sets ** can be computed later. */ PRIVATE struct state *getstate(struct lemon *); /* forward reference */ void FindStates(struct lemon *lemp) { struct symbol *sp; struct rule *rp; Configlist_init(); /* Find the start symbol */ if( lemp->start ){ sp = Symbol_find(lemp->start); if( sp==0 ){ ErrorMsg(lemp->filename,0, "The specified start symbol \"%s\" is not \ in a nonterminal of the grammar. \"%s\" will be used as the start \ symbol instead.",lemp->start,lemp->rule->lhs->name); lemp->errorcnt++; sp = lemp->rule->lhs; } }else{ sp = lemp->rule->lhs; } /* Make sure the start symbol doesn't occur on the right-hand side of ** any rule. Report an error if it does. (YACC would generate a new ** start symbol in this case.) */ for(rp=lemp->rule; rp; rp=rp->next){ int i; for(i=0; inrhs; i++){ if( rp->rhs[i]==sp ){ /* FIX ME: Deal with multiterminals */ ErrorMsg(lemp->filename,0, "The start symbol \"%s\" occurs on the \ right-hand side of a rule. This will result in a parser which \ does not work properly.",sp->name); lemp->errorcnt++; } } } /* The basis configuration set for the first state ** is all rules which have the start symbol as their ** left-hand side */ for(rp=sp->rule; rp; rp=rp->nextlhs){ struct config *newcfp; rp->lhsStart = 1; newcfp = Configlist_addbasis(rp,0); SetAdd(newcfp->fws,0); } /* Compute the first state. All other states will be ** computed automatically during the computation of the first one. ** The returned pointer to the first state is not used. */ (void)getstate(lemp); return; } /* Return a pointer to a state which is described by the configuration ** list which has been built from calls to Configlist_add. */ PRIVATE void buildshifts(struct lemon *, struct state *); /* Forwd ref */ PRIVATE struct state *getstate(struct lemon *lemp) { struct config *cfp, *bp; struct state *stp; /* Extract the sorted basis of the new state. The basis was constructed ** by prior calls to "Configlist_addbasis()". */ Configlist_sortbasis(); bp = Configlist_basis(); /* Get a state with the same basis */ stp = State_find(bp); if( stp ){ /* A state with the same basis already exists! Copy all the follow-set ** propagation links from the state under construction into the ** preexisting state, then return a pointer to the preexisting state */ struct config *x, *y; for(x=bp, y=stp->bp; x && y; x=x->bp, y=y->bp){ Plink_copy(&y->bplp,x->bplp); Plink_delete(x->fplp); x->fplp = x->bplp = 0; } cfp = Configlist_return(); Configlist_eat(cfp); }else{ /* This really is a new state. Construct all the details */ Configlist_closure(lemp); /* Compute the configuration closure */ Configlist_sort(); /* Sort the configuration closure */ cfp = Configlist_return(); /* Get a pointer to the config list */ stp = State_new(); /* A new state structure */ MemoryCheck(stp); stp->bp = bp; /* Remember the configuration basis */ stp->cfp = cfp; /* Remember the configuration closure */ stp->statenum = lemp->nstate++; /* Every state gets a sequence number */ stp->ap = 0; /* No actions, yet. */ State_insert(stp,stp->bp); /* Add to the state table */ buildshifts(lemp,stp); /* Recursively compute successor states */ } return stp; } /* ** Return true if two symbols are the same. */ int same_symbol(struct symbol *a, struct symbol *b) { int i; if( a==b ) return 1; if( a->type!=MULTITERMINAL ) return 0; if( b->type!=MULTITERMINAL ) return 0; if( a->nsubsym!=b->nsubsym ) return 0; for(i=0; insubsym; i++){ if( a->subsym[i]!=b->subsym[i] ) return 0; } return 1; } /* Construct all successor states to the given state. A "successor" ** state is any state which can be reached by a shift action. */ PRIVATE void buildshifts(struct lemon *lemp, struct state *stp) { struct config *cfp; /* For looping thru the config closure of "stp" */ struct config *bcfp; /* For the inner loop on config closure of "stp" */ struct config *newcfg; /* */ struct symbol *sp; /* Symbol following the dot in configuration "cfp" */ struct symbol *bsp; /* Symbol following the dot in configuration "bcfp" */ struct state *newstp; /* A pointer to a successor state */ /* Each configuration becomes complete after it contibutes to a successor ** state. Initially, all configurations are incomplete */ for(cfp=stp->cfp; cfp; cfp=cfp->next) cfp->status = INCOMPLETE; /* Loop through all configurations of the state "stp" */ for(cfp=stp->cfp; cfp; cfp=cfp->next){ if( cfp->status==COMPLETE ) continue; /* Already used by inner loop */ if( cfp->dot>=cfp->rp->nrhs ) continue; /* Can't shift this config */ Configlist_reset(); /* Reset the new config set */ sp = cfp->rp->rhs[cfp->dot]; /* Symbol after the dot */ /* For every configuration in the state "stp" which has the symbol "sp" ** following its dot, add the same configuration to the basis set under ** construction but with the dot shifted one symbol to the right. */ for(bcfp=cfp; bcfp; bcfp=bcfp->next){ if( bcfp->status==COMPLETE ) continue; /* Already used */ if( bcfp->dot>=bcfp->rp->nrhs ) continue; /* Can't shift this one */ bsp = bcfp->rp->rhs[bcfp->dot]; /* Get symbol after dot */ if( !same_symbol(bsp,sp) ) continue; /* Must be same as for "cfp" */ bcfp->status = COMPLETE; /* Mark this config as used */ newcfg = Configlist_addbasis(bcfp->rp,bcfp->dot+1); Plink_add(&newcfg->bplp,bcfp); } /* Get a pointer to the state described by the basis configuration set ** constructed in the preceding loop */ newstp = getstate(lemp); /* The state "newstp" is reached from the state "stp" by a shift action ** on the symbol "sp" */ if( sp->type==MULTITERMINAL ){ int i; for(i=0; insubsym; i++){ Action_add(&stp->ap,SHIFT,sp->subsym[i],(char*)newstp); } }else{ Action_add(&stp->ap,SHIFT,sp,(char *)newstp); } } } /* ** Construct the propagation links */ void FindLinks(struct lemon *lemp) { int i; struct config *cfp, *other; struct state *stp; struct plink *plp; /* Housekeeping detail: ** Add to every propagate link a pointer back to the state to ** which the link is attached. */ for(i=0; instate; i++){ stp = lemp->sorted[i]; for(cfp=stp->cfp; cfp; cfp=cfp->next){ cfp->stp = stp; } } /* Convert all backlinks into forward links. Only the forward ** links are used in the follow-set computation. */ for(i=0; instate; i++){ stp = lemp->sorted[i]; for(cfp=stp->cfp; cfp; cfp=cfp->next){ for(plp=cfp->bplp; plp; plp=plp->next){ other = plp->cfp; Plink_add(&other->fplp,cfp); } } } } /* Compute all followsets. ** ** A followset is the set of all symbols which can come immediately ** after a configuration. */ void FindFollowSets(struct lemon *lemp) { int i; struct config *cfp; struct plink *plp; int progress; int change; for(i=0; instate; i++){ for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){ cfp->status = INCOMPLETE; } } do{ progress = 0; for(i=0; instate; i++){ for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){ if( cfp->status==COMPLETE ) continue; for(plp=cfp->fplp; plp; plp=plp->next){ change = SetUnion(plp->cfp->fws,cfp->fws); if( change ){ plp->cfp->status = INCOMPLETE; progress = 1; } } cfp->status = COMPLETE; } } }while( progress ); } static int resolve_conflict(struct action *,struct action *); /* Compute the reduce actions, and resolve conflicts. */ void FindActions(struct lemon *lemp) { int i,j; struct config *cfp; struct state *stp; struct symbol *sp; struct rule *rp; /* Add all of the reduce actions ** A reduce action is added for each element of the followset of ** a configuration which has its dot at the extreme right. */ for(i=0; instate; i++){ /* Loop over all states */ stp = lemp->sorted[i]; for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */ if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */ for(j=0; jnterminal; j++){ if( SetFind(cfp->fws,j) ){ /* Add a reduce action to the state "stp" which will reduce by the ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */ Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); } } } } } /* Add the accepting token */ if( lemp->start ){ sp = Symbol_find(lemp->start); if( sp==0 ) sp = lemp->rule->lhs; }else{ sp = lemp->rule->lhs; } /* Add to the first state (which is always the starting state of the ** finite state machine) an action to ACCEPT if the lookahead is the ** start nonterminal. */ Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); /* Resolve conflicts */ for(i=0; instate; i++){ struct action *ap, *nap; struct state *stp; stp = lemp->sorted[i]; /* assert( stp->ap ); */ stp->ap = Action_sort(stp->ap); for(ap=stp->ap; ap && ap->next; ap=ap->next){ for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){ /* The two actions "ap" and "nap" have the same lookahead. ** Figure out which one should be used */ lemp->nconflict += resolve_conflict(ap,nap); } } } /* Report an error for each rule that can never be reduced. */ for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = LEMON_FALSE; for(i=0; instate; i++){ struct action *ap; for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){ if( ap->type==REDUCE ) ap->x.rp->canReduce = LEMON_TRUE; } } for(rp=lemp->rule; rp; rp=rp->next){ if( rp->canReduce ) continue; ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n"); lemp->errorcnt++; } } /* Resolve a conflict between the two given actions. If the ** conflict can't be resolved, return non-zero. ** ** NO LONGER TRUE: ** To resolve a conflict, first look to see if either action ** is on an error rule. In that case, take the action which ** is not associated with the error rule. If neither or both ** actions are associated with an error rule, then try to ** use precedence to resolve the conflict. ** ** If either action is a SHIFT, then it must be apx. This ** function won't work if apx->type==REDUCE and apy->type==SHIFT. */ static int resolve_conflict( struct action *apx, struct action *apy ){ struct symbol *spx, *spy; int errcnt = 0; assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */ if( apx->type==SHIFT && apy->type==SHIFT ){ apy->type = SSCONFLICT; errcnt++; } if( apx->type==SHIFT && apy->type==REDUCE ){ spx = apx->sp; spy = apy->x.rp->precsym; if( spy==0 || spx->prec<0 || spy->prec<0 ){ /* Not enough precedence information. */ apy->type = SRCONFLICT; errcnt++; }else if( spx->prec>spy->prec ){ /* higher precedence wins */ apy->type = RD_RESOLVED; }else if( spx->precprec ){ apx->type = SH_RESOLVED; }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */ apy->type = RD_RESOLVED; /* associativity */ }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */ apx->type = SH_RESOLVED; }else{ assert( spx->prec==spy->prec && spx->assoc==NONE ); apy->type = SRCONFLICT; errcnt++; } }else if( apx->type==REDUCE && apy->type==REDUCE ){ spx = apx->x.rp->precsym; spy = apy->x.rp->precsym; if( spx==0 || spy==0 || spx->prec<0 || spy->prec<0 || spx->prec==spy->prec ){ apy->type = RRCONFLICT; errcnt++; }else if( spx->prec>spy->prec ){ apy->type = RD_RESOLVED; }else if( spx->precprec ){ apx->type = RD_RESOLVED; } }else{ assert( apx->type==SH_RESOLVED || apx->type==RD_RESOLVED || apx->type==SSCONFLICT || apx->type==SRCONFLICT || apx->type==RRCONFLICT || apy->type==SH_RESOLVED || apy->type==RD_RESOLVED || apy->type==SSCONFLICT || apy->type==SRCONFLICT || apy->type==RRCONFLICT ); /* The REDUCE/SHIFT case cannot happen because SHIFTs come before ** REDUCEs on the list. If we reach this point it must be because ** the parser conflict had already been resolved. */ } return errcnt; } /********************* From the file "configlist.c" *************************/ /* ** Routines to processing a configuration list and building a state ** in the LEMON parser generator. */ static struct config *freelist = 0; /* List of free configurations */ static struct config *current = 0; /* Top of list of configurations */ static struct config **currentend = 0; /* Last on list of configs */ static struct config *basis = 0; /* Top of list of basis configs */ static struct config **basisend = 0; /* End of list of basis configs */ /* Return a pointer to a new configuration */ PRIVATE struct config *newconfig(){ struct config *newcfg; if( freelist==0 ){ int i; int amt = 3; freelist = (struct config *)calloc( amt, sizeof(struct config) ); if( freelist==0 ){ fprintf(stderr,"Unable to allocate memory for a new configuration."); exit(1); } for(i=0; inext; return newcfg; } /* The configuration "old" is no longer used */ PRIVATE void deleteconfig(struct config *old) { old->next = freelist; freelist = old; } /* Initialized the configuration list builder */ void Configlist_init(){ current = 0; currentend = ¤t; basis = 0; basisend = &basis; Configtable_init(); return; } /* Initialized the configuration list builder */ void Configlist_reset(){ current = 0; currentend = ¤t; basis = 0; basisend = &basis; Configtable_clear(0); return; } /* Add another configuration to the configuration list */ struct config *Configlist_add( struct rule *rp, /* The rule */ int dot /* Index into the RHS of the rule where the dot goes */ ){ struct config *cfp, model; assert( currentend!=0 ); model.rp = rp; model.dot = dot; cfp = Configtable_find(&model); if( cfp==0 ){ cfp = newconfig(); cfp->rp = rp; cfp->dot = dot; cfp->fws = SetNew(); cfp->stp = 0; cfp->fplp = cfp->bplp = 0; cfp->next = 0; cfp->bp = 0; *currentend = cfp; currentend = &cfp->next; Configtable_insert(cfp); } return cfp; } /* Add a basis configuration to the configuration list */ struct config *Configlist_addbasis(struct rule *rp, int dot) { struct config *cfp, model; assert( basisend!=0 ); assert( currentend!=0 ); model.rp = rp; model.dot = dot; cfp = Configtable_find(&model); if( cfp==0 ){ cfp = newconfig(); cfp->rp = rp; cfp->dot = dot; cfp->fws = SetNew(); cfp->stp = 0; cfp->fplp = cfp->bplp = 0; cfp->next = 0; cfp->bp = 0; *currentend = cfp; currentend = &cfp->next; *basisend = cfp; basisend = &cfp->bp; Configtable_insert(cfp); } return cfp; } /* Compute the closure of the configuration list */ void Configlist_closure(struct lemon *lemp) { struct config *cfp, *newcfp; struct rule *rp, *newrp; struct symbol *sp, *xsp; int i, dot; assert( currentend!=0 ); for(cfp=current; cfp; cfp=cfp->next){ rp = cfp->rp; dot = cfp->dot; if( dot>=rp->nrhs ) continue; sp = rp->rhs[dot]; if( sp->type==NONTERMINAL ){ if( sp->rule==0 && sp!=lemp->errsym ){ ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.", sp->name); lemp->errorcnt++; } for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){ newcfp = Configlist_add(newrp,0); for(i=dot+1; inrhs; i++){ xsp = rp->rhs[i]; if( xsp->type==TERMINAL ){ SetAdd(newcfp->fws,xsp->index); break; }else if( xsp->type==MULTITERMINAL ){ int k; for(k=0; knsubsym; k++){ SetAdd(newcfp->fws, xsp->subsym[k]->index); } break; }else{ SetUnion(newcfp->fws,xsp->firstset); if( xsp->lambda==LEMON_FALSE ) break; } } if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); } } } return; } /* Sort the configuration list */ void Configlist_sort(){ current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp); currentend = 0; return; } /* Sort the basis configuration list */ void Configlist_sortbasis(){ basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configcmp); basisend = 0; return; } /* Return a pointer to the head of the configuration list and ** reset the list */ struct config *Configlist_return(){ struct config *old; old = current; current = 0; currentend = 0; return old; } /* Return a pointer to the head of the configuration list and ** reset the list */ struct config *Configlist_basis(){ struct config *old; old = basis; basis = 0; basisend = 0; return old; } /* Free all elements of the given configuration list */ void Configlist_eat(struct config *cfp) { struct config *nextcfp; for(; cfp; cfp=nextcfp){ nextcfp = cfp->next; assert( cfp->fplp==0 ); assert( cfp->bplp==0 ); if( cfp->fws ) SetFree(cfp->fws); deleteconfig(cfp); } return; } /***************** From the file "error.c" *********************************/ /* ** Code for printing error message. */ void ErrorMsg(const char *filename, int lineno, const char *format, ...){ va_list ap; fprintf(stderr, "%s:%d: ", filename, lineno); va_start(ap, format); vfprintf(stderr,format,ap); va_end(ap); fprintf(stderr, "\n"); } /**************** From the file "main.c" ************************************/ /* ** Main program file for the LEMON parser generator. */ /* Report an out-of-memory condition and abort. This function ** is used mostly by the "MemoryCheck" macro in struct.h */ void memory_error(){ fprintf(stderr,"Out of memory. Aborting...\n"); exit(1); } static int nDefine = 0; /* Number of -D options on the command line */ static char **azDefine = 0; /* Name of the -D macros */ /* This routine is called with the argument to each -D command-line option. ** Add the macro defined to the azDefine array. */ static void handle_D_option(char *z){ char **paz; nDefine++; azDefine = (char **) realloc(azDefine, sizeof(azDefine[0])*nDefine); if( azDefine==0 ){ fprintf(stderr,"out of memory\n"); exit(1); } paz = &azDefine[nDefine-1]; *paz = (char *) malloc( lemonStrlen(z)+1 ); if( *paz==0 ){ fprintf(stderr,"out of memory\n"); exit(1); } strcpy(*paz, z); for(z=*paz; *z && *z!='='; z++){} *z = 0; } static char *user_outputname = NULL; static void handle_O_option(char *z){ user_outputname = (char *) malloc( lemonStrlen(z)+1 ); if( user_outputname ==0 ){ memory_error(); } strcpy(user_outputname, z); } static char *user_templatename = NULL; static void handle_T_option(char *z){ user_templatename = (char *) malloc( lemonStrlen(z)+1 ); if( user_templatename==0 ){ memory_error(); } strcpy(user_templatename, z); } /* The main program. Parse the command line and do it... */ int main(int argc, char **argv) { static int version = 0; static int rpflag = 0; static int basisflag = 0; static int compress = 0; static int quiet = 0; static int statistics = 0; static int mhflag = 0; static int nolinenosflag = 0; static int noResort = 0; static struct s_options options[] = { {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."}, {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."}, {OPT_FSTR, "D", (char*)handle_D_option, "Define an %ifdef macro."}, {OPT_FSTR, "T", (char*)handle_T_option, "Specify a template file."}, {OPT_FSTR, "O", (char*)handle_O_option, "Specify an output file."}, {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file."}, {OPT_FLAG, "l", (char*)&nolinenosflag, "Do not print #line statements."}, {OPT_FLAG, "p", (char*)&showPrecedenceConflict, "Show conflicts resolved by precedence rules"}, {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."}, {OPT_FLAG, "r", (char*)&noResort, "Do not sort or renumber states"}, {OPT_FLAG, "s", (char*)&statistics, "Print parser stats to standard output."}, {OPT_FLAG, "x", (char*)&version, "Print the version number."}, {OPT_FLAG,0,0,0} }; int i; int exitcode; struct lemon lem; OptInit(argv,options,stderr); if( version ){ printf("Lemon version 1.0\n"); exit(0); } if( OptNArgs()!=1 ){ fprintf(stderr,"Exactly one filename argument is required.\n"); exit(1); } memset(&lem, 0, sizeof(lem)); lem.errorcnt = 0; /* Initialize the machine */ Strsafe_init(); Symbol_init(); State_init(); lem.argv0 = argv[0]; lem.filename = OptArg(0); lem.basisflag = basisflag; lem.nolinenosflag = nolinenosflag; Symbol_new("$"); lem.errsym = Symbol_new("error"); lem.errsym->useCnt = 0; /* Parse the input file */ Parse(&lem); if( lem.errorcnt ) exit(lem.errorcnt); if( lem.nrule==0 ){ fprintf(stderr,"Empty grammar.\n"); exit(1); } /* Count and index the symbols of the grammar */ lem.nsymbol = Symbol_count(); Symbol_new("{default}"); lem.symbols = Symbol_arrayof(); for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*), Symbolcmpp); for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i; for(i=1; isupper(lem.symbols[i]->name[0]); i++); lem.nterminal = i; /* Generate a reprint of the grammar, if requested on the command line */ if( rpflag ){ Reprint(&lem); }else{ /* Initialize the size for all follow and first sets */ SetSize(lem.nterminal+1); /* Find the precedence for every production rule (that has one) */ FindRulePrecedences(&lem); /* Compute the lambda-nonterminals and the first-sets for every ** nonterminal */ FindFirstSets(&lem); /* Compute all LR(0) states. Also record follow-set propagation ** links so that the follow-set can be computed later */ lem.nstate = 0; FindStates(&lem); lem.sorted = State_arrayof(); /* Tie up loose ends on the propagation links */ FindLinks(&lem); /* Compute the follow set of every reducible configuration */ FindFollowSets(&lem); /* Compute the action tables */ FindActions(&lem); /* Compress the action tables */ if( compress==0 ) CompressTables(&lem); /* Reorder and renumber the states so that states with fewer choices ** occur at the end. This is an optimization that helps make the ** generated parser tables smaller. */ if( noResort==0 ) ResortStates(&lem); /* Generate a report of the parser generated. (the "y.output" file) */ if( !quiet ) ReportOutput(&lem); /* Generate the source code for the parser */ ReportTable(&lem, mhflag); /* Produce a header file for use by the scanner. (This step is ** omitted if the "-m" option is used because makeheaders will ** generate the file for us.) */ if( !mhflag ) ReportHeader(&lem); } if( statistics ){ printf("Parser statistics: %d terminals, %d nonterminals, %d rules\n", lem.nterminal, lem.nsymbol - lem.nterminal, lem.nrule); printf(" %d states, %d parser table entries, %d conflicts\n", lem.nstate, lem.tablesize, lem.nconflict); } if( lem.nconflict > 0 ){ fprintf(stderr,"%d parsing conflicts.\n",lem.nconflict); } /* return 0 on success, 1 on failure. */ exitcode = ((lem.errorcnt > 0) || (lem.nconflict > 0)) ? 1 : 0; exit(exitcode); return (exitcode); } /******************** From the file "msort.c" *******************************/ /* ** A generic merge-sort program. ** ** USAGE: ** Let "ptr" be a pointer to some structure which is at the head of ** a null-terminated list. Then to sort the list call: ** ** ptr = msort(ptr,&(ptr->next),cmpfnc); ** ** In the above, "cmpfnc" is a pointer to a function which compares ** two instances of the structure and returns an integer, as in ** strcmp. The second argument is a pointer to the pointer to the ** second element of the linked list. This address is used to compute ** the offset to the "next" field within the structure. The offset to ** the "next" field must be constant for all structures in the list. ** ** The function returns a new pointer which is the head of the list ** after sorting. ** ** ALGORITHM: ** Merge-sort. */ /* ** Return a pointer to the next structure in the linked list. */ #define NEXT(A) (*(char**)(((unsigned long)A)+offset)) /* ** Inputs: ** a: A sorted, null-terminated linked list. (May be null). ** b: A sorted, null-terminated linked list. (May be null). ** cmp: A pointer to the comparison function. ** offset: Offset in the structure to the "next" field. ** ** Return Value: ** A pointer to the head of a sorted list containing the elements ** of both a and b. ** ** Side effects: ** The "next" pointers for elements in the lists a and b are ** changed. */ static char *merge( char *a, char *b, int (*cmp)(const char*,const char*), int offset ){ char *ptr, *head; if( a==0 ){ head = b; }else if( b==0 ){ head = a; }else{ if( (*cmp)(a,b)<=0 ){ ptr = a; a = NEXT(a); }else{ ptr = b; b = NEXT(b); } head = ptr; while( a && b ){ if( (*cmp)(a,b)<=0 ){ NEXT(ptr) = a; ptr = a; a = NEXT(a); }else{ NEXT(ptr) = b; ptr = b; b = NEXT(b); } } if( a ) NEXT(ptr) = a; else NEXT(ptr) = b; } return head; } /* ** Inputs: ** list: Pointer to a singly-linked list of structures. ** next: Pointer to pointer to the second element of the list. ** cmp: A comparison function. ** ** Return Value: ** A pointer to the head of a sorted list containing the elements ** orginally in list. ** ** Side effects: ** The "next" pointers for elements in list are changed. */ #define LISTSIZE 30 static char *msort( char *list, char **next, int (*cmp)(const char*,const char*) ){ unsigned long offset; char *ep; char *set[LISTSIZE]; int i; offset = (unsigned long)next - (unsigned long)list; for(i=0; istate = WAITING_FOR_DECL_KEYWORD; }else if( islower(x[0]) ){ psp->lhs = Symbol_new(x); psp->nrhs = 0; psp->lhsalias = 0; psp->state = WAITING_FOR_ARROW; }else if( x[0]=='{' ){ if( psp->prevrule==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "There is no prior rule upon which to attach the code \ fragment which begins on this line."); psp->errorcnt++; }else if( psp->prevrule->code!=0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Code fragment beginning on this line is not the first \ to follow the previous rule."); psp->errorcnt++; }else{ psp->prevrule->line = psp->tokenlineno; psp->prevrule->code = &x[1]; } }else if( x[0]=='[' ){ psp->state = PRECEDENCE_MARK_1; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Token \"%s\" should be either \"%%\" or a nonterminal name.", x); psp->errorcnt++; } break; case PRECEDENCE_MARK_1: if( !isupper(x[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "The precedence symbol must be a terminal."); psp->errorcnt++; }else if( psp->prevrule==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "There is no prior rule to assign precedence \"[%s]\".",x); psp->errorcnt++; }else if( psp->prevrule->precsym!=0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Precedence mark on this line is not the first \ to follow the previous rule."); psp->errorcnt++; }else{ psp->prevrule->precsym = Symbol_new(x); } psp->state = PRECEDENCE_MARK_2; break; case PRECEDENCE_MARK_2: if( x[0]!=']' ){ ErrorMsg(psp->filename,psp->tokenlineno, "Missing \"]\" on precedence mark."); psp->errorcnt++; } psp->state = WAITING_FOR_DECL_OR_RULE; break; case WAITING_FOR_ARROW: if( x[0]==':' && x[1]==':' && x[2]=='=' ){ psp->state = IN_RHS; }else if( x[0]=='(' ){ psp->state = LHS_ALIAS_1; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Expected to see a \":\" following the LHS symbol \"%s\".", psp->lhs->name); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case LHS_ALIAS_1: if( isalpha(x[0]) ){ psp->lhsalias = x; psp->state = LHS_ALIAS_2; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "\"%s\" is not a valid alias for the LHS \"%s\"\n", x,psp->lhs->name); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case LHS_ALIAS_2: if( x[0]==')' ){ psp->state = LHS_ALIAS_3; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case LHS_ALIAS_3: if( x[0]==':' && x[1]==':' && x[2]=='=' ){ psp->state = IN_RHS; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Missing \"->\" following: \"%s(%s)\".", psp->lhs->name,psp->lhsalias); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case IN_RHS: if( x[0]=='.' ){ struct rule *rp; rp = (struct rule *)calloc( sizeof(struct rule) + sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs, 1); if( rp==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Can't allocate enough memory for this rule."); psp->errorcnt++; psp->prevrule = 0; }else{ int i; rp->ruleline = psp->tokenlineno; rp->rhs = (struct symbol**)&rp[1]; rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]); for(i=0; inrhs; i++){ rp->rhs[i] = psp->rhs[i]; rp->rhsalias[i] = psp->alias[i]; } rp->lhs = psp->lhs; rp->lhsalias = psp->lhsalias; rp->nrhs = psp->nrhs; rp->code = 0; rp->precsym = 0; rp->index = psp->gp->nrule++; rp->nextlhs = rp->lhs->rule; rp->lhs->rule = rp; rp->next = 0; if( psp->firstrule==0 ){ psp->firstrule = psp->lastrule = rp; }else{ psp->lastrule->next = rp; psp->lastrule = rp; } psp->prevrule = rp; } psp->state = WAITING_FOR_DECL_OR_RULE; }else if( isalpha(x[0]) ){ if( psp->nrhs>=MAXRHS ){ ErrorMsg(psp->filename,psp->tokenlineno, "Too many symbols on RHS of rule beginning at \"%s\".", x); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; }else{ psp->rhs[psp->nrhs] = Symbol_new(x); psp->alias[psp->nrhs] = 0; psp->nrhs++; } }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){ struct symbol *msp = psp->rhs[psp->nrhs-1]; if( msp->type!=MULTITERMINAL ){ struct symbol *origsp = msp; msp = (struct symbol *) calloc(1,sizeof(*msp)); memset(msp, 0, sizeof(*msp)); msp->type = MULTITERMINAL; msp->nsubsym = 1; msp->subsym = (struct symbol **) calloc(1,sizeof(struct symbol*)); msp->subsym[0] = origsp; msp->name = origsp->name; psp->rhs[psp->nrhs-1] = msp; } msp->nsubsym++; msp->subsym = (struct symbol **) realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]); if( islower(x[1]) || islower(msp->subsym[0]->name[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "Cannot form a compound containing a non-terminal"); psp->errorcnt++; } }else if( x[0]=='(' && psp->nrhs>0 ){ psp->state = RHS_ALIAS_1; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Illegal character on RHS of rule: \"%s\".",x); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case RHS_ALIAS_1: if( isalpha(x[0]) ){ psp->alias[psp->nrhs-1] = x; psp->state = RHS_ALIAS_2; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n", x,psp->rhs[psp->nrhs-1]->name); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case RHS_ALIAS_2: if( x[0]==')' ){ psp->state = IN_RHS; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case WAITING_FOR_DECL_KEYWORD: if( isalpha(x[0]) ){ psp->declkeyword = x; psp->declargslot = 0; psp->decllinenoslot = 0; psp->insertLineMacro = 1; psp->state = WAITING_FOR_DECL_ARG; if( strcmp(x,"name")==0 ){ psp->declargslot = &(psp->gp->name); psp->insertLineMacro = 0; }else if( strcmp(x,"include")==0 ){ psp->declargslot = &(psp->gp->include); }else if( strcmp(x,"code")==0 ){ psp->declargslot = &(psp->gp->extracode); }else if( strcmp(x,"token_destructor")==0 ){ psp->declargslot = &psp->gp->tokendest; }else if( strcmp(x,"default_destructor")==0 ){ psp->declargslot = &psp->gp->vardest; }else if( strcmp(x,"token_prefix")==0 ){ psp->declargslot = &psp->gp->tokenprefix; psp->insertLineMacro = 0; }else if( strcmp(x,"syntax_error")==0 ){ psp->declargslot = &(psp->gp->error); }else if( strcmp(x,"parse_accept")==0 ){ psp->declargslot = &(psp->gp->accept); }else if( strcmp(x,"parse_failure")==0 ){ psp->declargslot = &(psp->gp->failure); }else if( strcmp(x,"stack_overflow")==0 ){ psp->declargslot = &(psp->gp->overflow); }else if( strcmp(x,"extra_argument")==0 ){ psp->declargslot = &(psp->gp->arg); psp->insertLineMacro = 0; }else if( strcmp(x,"token_type")==0 ){ psp->declargslot = &(psp->gp->tokentype); psp->insertLineMacro = 0; }else if( strcmp(x,"default_type")==0 ){ psp->declargslot = &(psp->gp->vartype); psp->insertLineMacro = 0; }else if( strcmp(x,"stack_size")==0 ){ psp->declargslot = &(psp->gp->stacksize); psp->insertLineMacro = 0; }else if( strcmp(x,"start_symbol")==0 ){ psp->declargslot = &(psp->gp->start); psp->insertLineMacro = 0; }else if( strcmp(x,"left")==0 ){ psp->preccounter++; psp->declassoc = LEFT; psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; }else if( strcmp(x,"right")==0 ){ psp->preccounter++; psp->declassoc = RIGHT; psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; }else if( strcmp(x,"nonassoc")==0 ){ psp->preccounter++; psp->declassoc = NONE; psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; }else if( strcmp(x,"destructor")==0 ){ psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; }else if( strcmp(x,"type")==0 ){ psp->state = WAITING_FOR_DATATYPE_SYMBOL; }else if( strcmp(x,"fallback")==0 ){ psp->fallback = 0; psp->state = WAITING_FOR_FALLBACK_ID; }else if( strcmp(x,"wildcard")==0 ){ psp->state = WAITING_FOR_WILDCARD_ID; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Unknown declaration keyword: \"%%%s\".",x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Illegal declaration keyword: \"%s\".",x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } break; case WAITING_FOR_DESTRUCTOR_SYMBOL: if( !isalpha(x[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "Symbol name missing after %%destructor keyword"); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; }else{ struct symbol *sp = Symbol_new(x); psp->declargslot = &sp->destructor; psp->decllinenoslot = &sp->destLineno; psp->insertLineMacro = 1; psp->state = WAITING_FOR_DECL_ARG; } break; case WAITING_FOR_DATATYPE_SYMBOL: if( !isalpha(x[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "Symbol name missing after %%type keyword"); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; }else{ struct symbol *sp = Symbol_find(x); if((sp) && (sp->datatype)){ ErrorMsg(psp->filename,psp->tokenlineno, "Symbol %%type \"%s\" already defined", x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; }else{ if (!sp){ sp = Symbol_new(x); } psp->declargslot = &sp->datatype; psp->insertLineMacro = 0; psp->state = WAITING_FOR_DECL_ARG; } } break; case WAITING_FOR_PRECEDENCE_SYMBOL: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; }else if( isupper(x[0]) ){ struct symbol *sp; sp = Symbol_new(x); if( sp->prec>=0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Symbol \"%s\" has already be given a precedence.",x); psp->errorcnt++; }else{ sp->prec = psp->preccounter; sp->assoc = psp->declassoc; } }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Can't assign a precedence to \"%s\".",x); psp->errorcnt++; } break; case WAITING_FOR_DECL_ARG: if( x[0]=='{' || x[0]=='\"' || isalnum(x[0]) ){ const char *zOld, *zNew; char *zBuf, *z; int nOld, n, nLine, nNew, nBack; int addLineMacro; char zLine[50]; zNew = x; if( zNew[0]=='"' || zNew[0]=='{' ) zNew++; nNew = lemonStrlen(zNew); if( *psp->declargslot ){ zOld = *psp->declargslot; }else{ zOld = ""; } nOld = lemonStrlen(zOld); n = nOld + nNew + 20; addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro && (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0); if( addLineMacro ){ for(z=psp->filename, nBack=0; *z; z++){ if( *z=='\\' ) nBack++; } sprintf(zLine, "#line %d ", psp->tokenlineno); nLine = lemonStrlen(zLine); n += nLine + lemonStrlen(psp->filename) + nBack; } *psp->declargslot = (char *) realloc(*psp->declargslot, n); zBuf = *psp->declargslot + nOld; if( addLineMacro ){ if( nOld && zBuf[-1]!='\n' ){ *(zBuf++) = '\n'; } memcpy(zBuf, zLine, nLine); zBuf += nLine; *(zBuf++) = '"'; for(z=psp->filename; *z; z++){ if( *z=='\\' ){ *(zBuf++) = '\\'; } *(zBuf++) = *z; } *(zBuf++) = '"'; *(zBuf++) = '\n'; } if( psp->decllinenoslot && psp->decllinenoslot[0]==0 ){ psp->decllinenoslot[0] = psp->tokenlineno; } memcpy(zBuf, zNew, nNew); zBuf += nNew; *zBuf = 0; psp->state = WAITING_FOR_DECL_OR_RULE; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Illegal argument to %%%s: %s",psp->declkeyword,x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } break; case WAITING_FOR_FALLBACK_ID: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; }else if( !isupper(x[0]) ){ ErrorMsg(psp->filename, psp->tokenlineno, "%%fallback argument \"%s\" should be a token", x); psp->errorcnt++; }else{ struct symbol *sp = Symbol_new(x); if( psp->fallback==0 ){ psp->fallback = sp; }else if( sp->fallback ){ ErrorMsg(psp->filename, psp->tokenlineno, "More than one fallback assigned to token %s", x); psp->errorcnt++; }else{ sp->fallback = psp->fallback; psp->gp->has_fallback = 1; } } break; case WAITING_FOR_WILDCARD_ID: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; }else if( !isupper(x[0]) ){ ErrorMsg(psp->filename, psp->tokenlineno, "%%wildcard argument \"%s\" should be a token", x); psp->errorcnt++; }else{ struct symbol *sp = Symbol_new(x); if( psp->gp->wildcard==0 ){ psp->gp->wildcard = sp; }else{ ErrorMsg(psp->filename, psp->tokenlineno, "Extra wildcard to token: %s", x); psp->errorcnt++; } } break; case RESYNC_AFTER_RULE_ERROR: /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; ** break; */ case RESYNC_AFTER_DECL_ERROR: if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; if( x[0]=='%' ) psp->state = WAITING_FOR_DECL_KEYWORD; break; } } /* Run the preprocessor over the input file text. The global variables ** azDefine[0] through azDefine[nDefine-1] contains the names of all defined ** macros. This routine looks for "%ifdef" and "%ifndef" and "%endif" and ** comments them out. Text in between is also commented out as appropriate. */ static void preprocess_input(char *z){ int i, j, k, n; int exclude = 0; int start = 0; int lineno = 1; int start_lineno = 1; for(i=0; z[i]; i++){ if( z[i]=='\n' ) lineno++; if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue; if( strncmp(&z[i],"%endif",6)==0 && isspace(z[i+6]) ){ if( exclude ){ exclude--; if( exclude==0 ){ for(j=start; jfilename; ps.errorcnt = 0; ps.state = INITIALIZE; /* Begin by reading the input file */ fp = fopen(ps.filename,"rb"); if( fp==0 ){ ErrorMsg(ps.filename,0,"Can't open this file for reading."); gp->errorcnt++; return; } fseek(fp,0,2); filesize = ftell(fp); rewind(fp); filebuf = (char *)malloc( filesize+1 ); if( filebuf==0 ){ ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.", filesize+1); gp->errorcnt++; fclose(fp); return; } if( fread(filebuf,1,filesize,fp)!=filesize ){ ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.", filesize); free(filebuf); gp->errorcnt++; fclose(fp); return; } fclose(fp); filebuf[filesize] = 0; /* Make an initial pass through the file to handle %ifdef and %ifndef */ preprocess_input(filebuf); /* Now scan the text of the input file */ lineno = 1; for(cp=filebuf; (c= *cp)!=0; ){ if( c=='\n' ) lineno++; /* Keep track of the line number */ if( isspace(c) ){ cp++; continue; } /* Skip all white space */ if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */ cp+=2; while( (c= *cp)!=0 && c!='\n' ) cp++; continue; } if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */ cp+=2; while( (c= *cp)!=0 && (c!='/' || cp[-1]!='*') ){ if( c=='\n' ) lineno++; cp++; } if( c ) cp++; continue; } ps.tokenstart = cp; /* Mark the beginning of the token */ ps.tokenlineno = lineno; /* Linenumber on which token begins */ if( c=='\"' ){ /* String literals */ cp++; while( (c= *cp)!=0 && c!='\"' ){ if( c=='\n' ) lineno++; cp++; } if( c==0 ){ ErrorMsg(ps.filename,startline, "String starting on this line is not terminated before the end of the file."); ps.errorcnt++; nextcp = cp; }else{ nextcp = cp+1; } }else if( c=='{' ){ /* A block of C code */ int level; cp++; for(level=1; (c= *cp)!=0 && (level>1 || c!='}'); cp++){ if( c=='\n' ) lineno++; else if( c=='{' ) level++; else if( c=='}' ) level--; else if( c=='/' && cp[1]=='*' ){ /* Skip comments */ int prevc; cp = &cp[2]; prevc = 0; while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){ if( c=='\n' ) lineno++; prevc = c; cp++; } }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */ cp = &cp[2]; while( (c= *cp)!=0 && c!='\n' ) cp++; if( c ) lineno++; }else if( c=='\'' || c=='\"' ){ /* String a character literals */ int startchar, prevc; startchar = c; prevc = 0; for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){ if( c=='\n' ) lineno++; if( prevc=='\\' ) prevc = 0; else prevc = c; } } } if( c==0 ){ ErrorMsg(ps.filename,ps.tokenlineno, "C code starting on this line is not terminated before the end of the file."); ps.errorcnt++; nextcp = cp; }else{ nextcp = cp+1; } }else if( isalnum(c) ){ /* Identifiers */ while( (c= *cp)!=0 && (isalnum(c) || c=='_') ) cp++; nextcp = cp; }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */ cp += 3; nextcp = cp; }else if( (c=='/' || c=='|') && isalpha(cp[1]) ){ cp += 2; while( (c = *cp)!=0 && (isalnum(c) || c=='_') ) cp++; nextcp = cp; }else{ /* All other (one character) operators */ cp++; nextcp = cp; } c = *cp; *cp = 0; /* Null terminate the token */ parseonetoken(&ps); /* Parse the token */ *cp = c; /* Restore the buffer */ cp = nextcp; } free(filebuf); /* Release the buffer after parsing */ gp->rule = ps.firstrule; gp->errorcnt = ps.errorcnt; } /*************************** From the file "plink.c" *********************/ /* ** Routines processing configuration follow-set propagation links ** in the LEMON parser generator. */ static struct plink *plink_freelist = 0; /* Allocate a new plink */ struct plink *Plink_new(){ struct plink *newlink; if( plink_freelist==0 ){ int i; int amt = 100; plink_freelist = (struct plink *)calloc( amt, sizeof(struct plink) ); if( plink_freelist==0 ){ fprintf(stderr, "Unable to allocate memory for a new follow-set propagation link.\n"); exit(1); } for(i=0; inext; return newlink; } /* Add a plink to a plink list */ void Plink_add(struct plink **plpp, struct config *cfp) { struct plink *newlink; newlink = Plink_new(); newlink->next = *plpp; *plpp = newlink; newlink->cfp = cfp; } /* Transfer every plink on the list "from" to the list "to" */ void Plink_copy(struct plink **to, struct plink *from) { struct plink *nextpl; while( from ){ nextpl = from->next; from->next = *to; *to = from; from = nextpl; } } /* Delete every plink on the list */ void Plink_delete(struct plink *plp) { struct plink *nextpl; while( plp ){ nextpl = plp->next; plp->next = plink_freelist; plink_freelist = plp; plp = nextpl; } } /*********************** From the file "report.c" **************************/ /* ** Procedures for generating reports and tables in the LEMON parser generator. */ /* Generate a filename with the given suffix. Space to hold the ** name comes from malloc() and must be freed by the calling ** function. */ PRIVATE char *file_makename(const char *filename, const char *suffix) { char *name; char *cp; name = (char*)malloc( lemonStrlen(filename) + lemonStrlen(suffix) + 5 ); if( name==0 ){ fprintf(stderr,"Can't allocate space for a filename.\n"); exit(1); } strcpy(name,filename); cp = strrchr(name,'.'); if( cp ) *cp = 0; strcat(name,suffix); return name; } /* Open a file with a name based on the name of the input file, ** but with a different (specified) suffix, and return a pointer ** to the stream */ PRIVATE FILE *file_open( struct lemon *lemp, const char *suffix, const char *mode ){ FILE *fp; if( lemp->outname ) free(lemp->outname); lemp->outname = file_makename(lemp->filename, suffix); fp = fopen(lemp->outname,mode); if( fp==0 && *mode=='w' ){ fprintf(stderr,"Can't open file \"%s\".\n",lemp->outname); lemp->errorcnt++; return 0; } return fp; } /* Duplicate the input file without comments and without actions ** on rules */ void Reprint(struct lemon *lemp) { struct rule *rp; struct symbol *sp; int i, j, maxlen, len, ncolumns, skip; printf("// Reprint of input file \"%s\".\n// Symbols:\n",lemp->filename); maxlen = 10; for(i=0; insymbol; i++){ sp = lemp->symbols[i]; len = lemonStrlen(sp->name); if( len>maxlen ) maxlen = len; } ncolumns = 76/(maxlen+5); if( ncolumns<1 ) ncolumns = 1; skip = (lemp->nsymbol + ncolumns - 1)/ncolumns; for(i=0; insymbol; j+=skip){ sp = lemp->symbols[j]; assert( sp->index==j ); printf(" %3d %-*.*s",j,maxlen,maxlen,sp->name); } printf("\n"); } for(rp=lemp->rule; rp; rp=rp->next){ printf("%s",rp->lhs->name); /* if( rp->lhsalias ) printf("(%s)",rp->lhsalias); */ printf(" ::="); for(i=0; inrhs; i++){ sp = rp->rhs[i]; printf(" %s", sp->name); if( sp->type==MULTITERMINAL ){ for(j=1; jnsubsym; j++){ printf("|%s", sp->subsym[j]->name); } } /* if( rp->rhsalias[i] ) printf("(%s)",rp->rhsalias[i]); */ } printf("."); if( rp->precsym ) printf(" [%s]",rp->precsym->name); /* if( rp->code ) printf("\n %s",rp->code); */ printf("\n"); } } void ConfigPrint(FILE *fp, struct config *cfp) { struct rule *rp; struct symbol *sp; int i, j; rp = cfp->rp; fprintf(fp,"%s ::=",rp->lhs->name); for(i=0; i<=rp->nrhs; i++){ if( i==cfp->dot ) fprintf(fp," *"); if( i==rp->nrhs ) break; sp = rp->rhs[i]; fprintf(fp," %s", sp->name); if( sp->type==MULTITERMINAL ){ for(j=1; jnsubsym; j++){ fprintf(fp,"|%s",sp->subsym[j]->name); } } } } /* #define TEST */ #if 0 /* Print a set */ PRIVATE void SetPrint(out,set,lemp) FILE *out; char *set; struct lemon *lemp; { int i; char *spacer; spacer = ""; fprintf(out,"%12s[",""); for(i=0; interminal; i++){ if( SetFind(set,i) ){ fprintf(out,"%s%s",spacer,lemp->symbols[i]->name); spacer = " "; } } fprintf(out,"]\n"); } /* Print a plink chain */ PRIVATE void PlinkPrint(out,plp,tag) FILE *out; struct plink *plp; char *tag; { while( plp ){ fprintf(out,"%12s%s (state %2d) ","",tag,plp->cfp->stp->statenum); ConfigPrint(out,plp->cfp); fprintf(out,"\n"); plp = plp->next; } } #endif /* Print an action to the given file descriptor. Return FALSE if ** nothing was actually printed. */ int PrintAction(struct action *ap, FILE *fp, int indent){ int result = 1; switch( ap->type ){ case SHIFT: fprintf(fp,"%*s shift %d",indent,ap->sp->name,ap->x.stp->statenum); break; case REDUCE: fprintf(fp,"%*s reduce %d",indent,ap->sp->name,ap->x.rp->index); break; case ACCEPT: fprintf(fp,"%*s accept",indent,ap->sp->name); break; case ERROR: fprintf(fp,"%*s error",indent,ap->sp->name); break; case SRCONFLICT: case RRCONFLICT: fprintf(fp,"%*s reduce %-3d ** Parsing conflict **", indent,ap->sp->name,ap->x.rp->index); break; case SSCONFLICT: fprintf(fp,"%*s shift %-3d ** Parsing conflict **", indent,ap->sp->name,ap->x.stp->statenum); break; case SH_RESOLVED: if( showPrecedenceConflict ){ fprintf(fp,"%*s shift %-3d -- dropped by precedence", indent,ap->sp->name,ap->x.stp->statenum); }else{ result = 0; } break; case RD_RESOLVED: if( showPrecedenceConflict ){ fprintf(fp,"%*s reduce %-3d -- dropped by precedence", indent,ap->sp->name,ap->x.rp->index); }else{ result = 0; } break; case NOT_USED: result = 0; break; } return result; } /* Generate the "y.output" log file */ void ReportOutput(struct lemon *lemp) { int i; struct state *stp; struct config *cfp; struct action *ap; FILE *fp; fp = file_open(lemp,".out","wb"); if( fp==0 ) return; for(i=0; instate; i++){ stp = lemp->sorted[i]; fprintf(fp,"State %d:\n",stp->statenum); if( lemp->basisflag ) cfp=stp->bp; else cfp=stp->cfp; while( cfp ){ char buf[20]; if( cfp->dot==cfp->rp->nrhs ){ sprintf(buf,"(%d)",cfp->rp->index); fprintf(fp," %5s ",buf); }else{ fprintf(fp," "); } ConfigPrint(fp,cfp); fprintf(fp,"\n"); #if 0 SetPrint(fp,cfp->fws,lemp); PlinkPrint(fp,cfp->fplp,"To "); PlinkPrint(fp,cfp->bplp,"From"); #endif if( lemp->basisflag ) cfp=cfp->bp; else cfp=cfp->next; } fprintf(fp,"\n"); for(ap=stp->ap; ap; ap=ap->next){ if( PrintAction(ap,fp,30) ) fprintf(fp,"\n"); } fprintf(fp,"\n"); } fprintf(fp, "----------------------------------------------------\n"); fprintf(fp, "Symbols:\n"); for(i=0; insymbol; i++){ int j; struct symbol *sp; sp = lemp->symbols[i]; fprintf(fp, " %3d: %s", i, sp->name); if( sp->type==NONTERMINAL ){ fprintf(fp, ":"); if( sp->lambda ){ fprintf(fp, " "); } for(j=0; jnterminal; j++){ if( sp->firstset && SetFind(sp->firstset, j) ){ fprintf(fp, " %s", lemp->symbols[j]->name); } } } fprintf(fp, "\n"); } fclose(fp); return; } /* Search for the file "name" which is in the same directory as ** the exacutable */ PRIVATE char *pathsearch(char *argv0, char *name, int modemask) { const char *pathlist; char *pathbufptr; char *pathbuf; char *path,*cp; char c; #ifdef __WIN32__ cp = strrchr(argv0,'\\'); #else cp = strrchr(argv0,'/'); #endif if( cp ){ c = *cp; *cp = 0; path = (char *)malloc( lemonStrlen(argv0) + lemonStrlen(name) + 2 ); if( path ) sprintf(path,"%s/%s",argv0,name); *cp = c; }else{ pathlist = getenv("PATH"); if( pathlist==0 ) pathlist = ".:/bin:/usr/bin"; pathbuf = (char *) malloc( lemonStrlen(pathlist) + 1 ); path = (char *)malloc( lemonStrlen(pathlist)+lemonStrlen(name)+2 ); if( (pathbuf != 0) && (path!=0) ){ pathbufptr = pathbuf; strcpy(pathbuf, pathlist); while( *pathbuf ){ cp = strchr(pathbuf,':'); if( cp==0 ) cp = &pathbuf[lemonStrlen(pathbuf)]; c = *cp; *cp = 0; sprintf(path,"%s/%s",pathbuf,name); *cp = c; if( c==0 ) pathbuf[0] = 0; else pathbuf = &cp[1]; if( access(path,modemask)==0 ) break; } free(pathbufptr); } } return path; } /* Given an action, compute the integer value for that action ** which is to be put in the action table of the generated machine. ** Return negative if no action should be generated. */ PRIVATE int compute_action(struct lemon *lemp, struct action *ap) { int act; switch( ap->type ){ case SHIFT: act = ap->x.stp->statenum; break; case REDUCE: act = ap->x.rp->index + lemp->nstate; break; case ERROR: act = lemp->nstate + lemp->nrule; break; case ACCEPT: act = lemp->nstate + lemp->nrule + 1; break; default: act = -1; break; } return act; } #define LINESIZE 1000 /* The next cluster of routines are for reading the template file ** and writing the results to the generated parser */ /* The first function transfers data from "in" to "out" until ** a line is seen which begins with "%%". The line number is ** tracked. ** ** if name!=0, then any word that begin with "Parse" is changed to ** begin with *name instead. */ PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno) { int i, iStart; char line[LINESIZE]; while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){ (*lineno)++; iStart = 0; if( name ){ for(i=0; line[i]; i++){ if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0 && (i==0 || !isalpha(line[i-1])) ){ if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]); fprintf(out,"%s",name); i += 4; iStart = i+1; } } } fprintf(out,"%s",&line[iStart]); } } /* The next function finds the template file and opens it, returning ** a pointer to the opened file. */ PRIVATE FILE *tplt_open(struct lemon *lemp) { static char templatename[] = "lempar.c"; char buf[1000]; FILE *in; char *tpltname; char *cp; /* first, see if user specified a template filename on the command line. */ if (user_templatename != 0) { if( access(user_templatename,004)==-1 ){ fprintf(stderr,"Can't find the parser driver template file \"%s\".\n", user_templatename); lemp->errorcnt++; return 0; } in = fopen(user_templatename,"rb"); if( in==0 ){ fprintf(stderr,"Can't open the template file \"%s\".\n",user_templatename); lemp->errorcnt++; return 0; } return in; } cp = strrchr(lemp->filename,'.'); if( cp ){ sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); }else{ sprintf(buf,"%s.lt",lemp->filename); } if( access(buf,004)==0 ){ tpltname = buf; }else if( access(templatename,004)==0 ){ tpltname = templatename; }else{ tpltname = pathsearch(lemp->argv0,templatename,0); } if( tpltname==0 ){ fprintf(stderr,"Can't find the parser driver template file \"%s\".\n", templatename); lemp->errorcnt++; return 0; } in = fopen(tpltname,"rb"); if( in==0 ){ fprintf(stderr,"Can't open the template file \"%s\".\n",templatename); lemp->errorcnt++; return 0; } return in; } /* Print a #line directive line to the output file. */ PRIVATE void tplt_linedir(FILE *out, int lineno, char *filename) { fprintf(out,"#line %d \"",lineno); while( *filename ){ if( *filename == '\\' ) putc('\\',out); putc(*filename,out); filename++; } fprintf(out,"\"\n"); } /* Print a string to the file and keep the linenumber up to date */ PRIVATE void tplt_print(FILE *out, struct lemon *lemp, char *str, int *lineno) { if( str==0 ) return; while( *str ){ putc(*str,out); if( *str=='\n' ) (*lineno)++; str++; } if( str[-1]!='\n' ){ putc('\n',out); (*lineno)++; } if (!lemp->nolinenosflag) { (*lineno)++; tplt_linedir(out,*lineno,lemp->outname); } return; } /* ** The following routine emits code for the destructor for the ** symbol sp */ void emit_destructor_code( FILE *out, struct symbol *sp, struct lemon *lemp, int *lineno ){ char *cp = 0; if( sp->type==TERMINAL ){ cp = lemp->tokendest; if( cp==0 ) return; fprintf(out,"{\n"); (*lineno)++; }else if( sp->destructor ){ cp = sp->destructor; fprintf(out,"{\n"); (*lineno)++; if (!lemp->nolinenosflag) { (*lineno)++; tplt_linedir(out,sp->destLineno,lemp->filename); } }else if( lemp->vardest ){ cp = lemp->vardest; if( cp==0 ) return; fprintf(out,"{\n"); (*lineno)++; }else{ assert( 0 ); /* Cannot happen */ } for(; *cp; cp++){ if( *cp=='$' && cp[1]=='$' ){ fprintf(out,"(yypminor->yy%d)",sp->dtnum); cp++; continue; } if( *cp=='\n' ) (*lineno)++; fputc(*cp,out); } fprintf(out,"\n"); (*lineno)++; if (!lemp->nolinenosflag) { (*lineno)++; tplt_linedir(out,*lineno,lemp->outname); } fprintf(out,"}\n"); (*lineno)++; return; } /* ** Return TRUE (non-zero) if the given symbol has a destructor. */ int has_destructor(struct symbol *sp, struct lemon *lemp) { int ret; if( sp->type==TERMINAL ){ ret = lemp->tokendest!=0; }else{ ret = lemp->vardest!=0 || sp->destructor!=0; } return ret; } /* ** Append text to a dynamically allocated string. If zText is 0 then ** reset the string to be empty again. Always return the complete text ** of the string (which is overwritten with each call). ** ** n bytes of zText are stored. If n==0 then all of zText up to the first ** \000 terminator is stored. zText can contain up to two instances of ** %d. The values of p1 and p2 are written into the first and second ** %d. ** ** If n==-1, then the previous character is overwritten. */ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){ static char empty[1] = { 0 }; static char *z = 0; static int alloced = 0; static int used = 0; int c; char zInt[40]; if( zText==0 ){ used = 0; return z; } if( n<=0 ){ if( n<0 ){ used += n; assert( used>=0 ); } n = lemonStrlen(zText); } if( (int) (n+sizeof(zInt)*2+used) >= alloced ){ alloced = n + sizeof(zInt)*2 + used + 200; z = (char *) realloc(z, alloced); } if( z==0 ) return empty; while( n-- > 0 ){ c = *(zText++); if( c=='%' && n>0 && zText[0]=='d' ){ sprintf(zInt, "%d", p1); p1 = p2; strcpy(&z[used], zInt); used += lemonStrlen(&z[used]); zText++; n--; }else{ z[used++] = c; } } z[used] = 0; return z; } /* ** zCode is a string that is the action associated with a rule. Expand ** the symbols in this string so that the refer to elements of the parser ** stack. */ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){ char *cp, *xp; int i; char lhsused = 0; /* True if the LHS element has been used */ char used[MAXRHS]; /* True for each RHS element which is used */ for(i=0; inrhs; i++) used[i] = 0; lhsused = 0; if( rp->code==0 ){ static char newlinestr[2] = { '\n', '\0' }; rp->code = newlinestr; rp->line = rp->ruleline; } append_str(0,0,0,0); /* This const cast is wrong but harmless, if we're careful. */ for(cp=(char *)rp->code; *cp; cp++){ if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){ char saved; for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++); saved = *xp; *xp = 0; if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0); cp = xp; lhsused = 1; }else{ for(i=0; inrhs; i++){ if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){ if( cp!=rp->code && cp[-1]=='@' ){ /* If the argument is of the form @X then substituted ** the token number of X, not the value of X */ append_str("yymsp[%d].major",-1,i-rp->nrhs+1,0); }else{ struct symbol *sp = rp->rhs[i]; int dtnum; if( sp->type==MULTITERMINAL ){ dtnum = sp->subsym[0]->dtnum; }else{ dtnum = sp->dtnum; } append_str("yymsp[%d].minor.yy%d",0,i-rp->nrhs+1, dtnum); } cp = xp; used[i] = 1; break; } } } *xp = saved; } append_str(cp, 1, 0, 0); } /* End loop */ /* Check to make sure the LHS has been used */ if( rp->lhsalias && !lhsused ){ ErrorMsg(lemp->filename,rp->ruleline, "Label \"%s\" for \"%s(%s)\" is never used.", rp->lhsalias,rp->lhs->name,rp->lhsalias); lemp->errorcnt++; } /* Generate destructor code for RHS symbols which are not used in the ** reduce code */ for(i=0; inrhs; i++){ if( rp->rhsalias[i] && !used[i] ){ ErrorMsg(lemp->filename,rp->ruleline, "Label %s for \"%s(%s)\" is never used.", rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]); lemp->errorcnt++; }else if( rp->rhsalias[i]==0 ){ if( has_destructor(rp->rhs[i],lemp) ){ append_str(" yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0, rp->rhs[i]->index,i-rp->nrhs+1); }else{ /* No destructor defined for this term */ } } } if( rp->code ){ cp = append_str(0,0,0,0); rp->code = Strsafe(cp?cp:""); } } /* ** Generate code which executes when the rule "rp" is reduced. Write ** the code to "out". Make sure lineno stays up-to-date. */ PRIVATE void emit_code( FILE *out, struct rule *rp, struct lemon *lemp, int *lineno ){ const char *cp; /* Generate code to do the reduce action */ if( rp->code ){ if (!lemp->nolinenosflag) { (*lineno)++; tplt_linedir(out,rp->line,lemp->filename); } fprintf(out,"{%s",rp->code); for(cp=rp->code; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; } /* End loop */ fprintf(out,"}\n"); (*lineno)++; if (!lemp->nolinenosflag) { (*lineno)++; tplt_linedir(out,*lineno,lemp->outname); } } /* End if( rp->code ) */ return; } /* ** Print the definition of the union used for the parser's data stack. ** This union contains fields for every possible data type for tokens ** and nonterminals. In the process of computing and printing this ** union, also set the ".dtnum" field of every terminal and nonterminal ** symbol. */ void print_stack_union( FILE *out, /* The output stream */ struct lemon *lemp, /* The main info structure for this parser */ int *plineno, /* Pointer to the line number */ int mhflag /* True if generating makeheaders output */ ){ int lineno = *plineno; /* The line number of the output */ char **types; /* A hash table of datatypes */ int arraysize; /* Size of the "types" array */ int maxdtlength; /* Maximum length of any ".datatype" field. */ char *stddt; /* Standardized name for a datatype */ int i,j; /* Loop counters */ int hash; /* For hashing the name of a type */ const char *name; /* Name of the parser */ /* Allocate and initialize types[] and allocate stddt[] */ arraysize = lemp->nsymbol * 2; types = (char**)calloc( arraysize, sizeof(char*) ); if( types==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); } for(i=0; ivartype ){ maxdtlength = lemonStrlen(lemp->vartype); } for(i=0; insymbol; i++){ int len; struct symbol *sp = lemp->symbols[i]; if( sp->datatype==0 ) continue; len = lemonStrlen(sp->datatype); if( len>maxdtlength ) maxdtlength = len; } stddt = (char*)malloc( maxdtlength*2 + 1 ); if( stddt==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); } /* Build a hash table of datatypes. The ".dtnum" field of each symbol ** is filled in with the hash index plus 1. A ".dtnum" value of 0 is ** used for terminal symbols. If there is no %default_type defined then ** 0 is also used as the .dtnum value for nonterminals which do not specify ** a datatype using the %type directive. */ for(i=0; insymbol; i++){ struct symbol *sp = lemp->symbols[i]; char *cp; if( sp==lemp->errsym ){ sp->dtnum = arraysize+1; continue; } if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){ sp->dtnum = 0; continue; } cp = sp->datatype; if( cp==0 ) cp = lemp->vartype; j = 0; while( isspace(*cp) ) cp++; while( *cp ) stddt[j++] = *cp++; while( j>0 && isspace(stddt[j-1]) ) j--; stddt[j] = 0; if( lemp->tokentype && strcmp(stddt, lemp->tokentype)==0 ){ sp->dtnum = 0; continue; } hash = 0; for(j=0; stddt[j]; j++){ hash = hash*53 + stddt[j]; } hash = (hash & 0x7fffffff)%arraysize; while( types[hash] ){ if( strcmp(types[hash],stddt)==0 ){ sp->dtnum = hash + 1; break; } hash++; if( hash>=arraysize ) hash = 0; } if( types[hash]==0 ){ sp->dtnum = hash + 1; types[hash] = (char*)malloc( lemonStrlen(stddt)+1 ); if( types[hash]==0 ){ fprintf(stderr,"Out of memory.\n"); exit(1); } strcpy(types[hash],stddt); } } /* Print out the definition of YYTOKENTYPE and YYMINORTYPE */ name = lemp->name ? lemp->name : "Parse"; lineno = *plineno; if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; } fprintf(out,"#define %sTOKENTYPE %s\n",name, lemp->tokentype?lemp->tokentype:"void*"); lineno++; if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } fprintf(out,"typedef union {\n"); lineno++; fprintf(out," int yyinit;\n"); lineno++; fprintf(out," %sTOKENTYPE yy0;\n",name); lineno++; for(i=0; ierrsym->useCnt ){ fprintf(out," int yy%d;\n",lemp->errsym->dtnum); lineno++; } free(stddt); free(types); fprintf(out,"} YYMINORTYPE;\n"); lineno++; *plineno = lineno; } /* ** Return the name of a C datatype able to represent values between ** lwr and upr, inclusive. */ static const char *minimum_size_type(int lwr, int upr){ if( lwr>=0 ){ if( upr<=255 ){ return "unsigned char"; }else if( upr<65535 ){ return "unsigned short int"; }else{ return "unsigned int"; } }else if( lwr>=-127 && upr<=127 ){ return "signed char"; }else if( lwr>=-32767 && upr<32767 ){ return "short"; }else{ return "int"; } } /* ** Each state contains a set of token transaction and a set of ** nonterminal transactions. Each of these sets makes an instance ** of the following structure. An array of these structures is used ** to order the creation of entries in the yy_action[] table. */ struct axset { struct state *stp; /* A pointer to a state */ int isTkn; /* True to use tokens. False for non-terminals */ int nAction; /* Number of actions */ int iOrder; /* Original order of action sets */ }; /* ** Compare to axset structures for sorting purposes */ static int axset_compare(const void *a, const void *b){ struct axset *p1 = (struct axset*)a; struct axset *p2 = (struct axset*)b; int c; c = p2->nAction - p1->nAction; if( c==0 ){ c = p2->iOrder - p1->iOrder; } assert( c!=0 || p1==p2 ); return c; } /* ** Write text on "out" that describes the rule "rp". */ static void writeRuleText(FILE *out, struct rule *rp){ int j; fprintf(out,"%s ::=", rp->lhs->name); for(j=0; jnrhs; j++){ struct symbol *sp = rp->rhs[j]; fprintf(out," %s", sp->name); if( sp->type==MULTITERMINAL ){ int k; for(k=1; knsubsym; k++){ fprintf(out,"|%s",sp->subsym[k]->name); } } } } /* Generate C source code for the parser */ void ReportTable( struct lemon *lemp, int mhflag /* Output in makeheaders format if true */ ){ FILE *out, *in; char line[LINESIZE]; int lineno; struct state *stp; struct action *ap; struct rule *rp; struct acttab *pActtab; int i, j, n; const char *name; int mnTknOfst, mxTknOfst; int mnNtOfst, mxNtOfst; struct axset *ax; in = tplt_open(lemp); if( in==0 ) return; if ( user_outputname ){ // XXX - This should be moved to file_open out = fopen(user_outputname, "wb"); if ( lemp->outname ) free(lemp->outname); lemp->outname = strdup(user_outputname); } else { out = file_open(lemp,".c","wb"); } if( out==0 ){ fclose(in); return; } lineno = 1; tplt_xfer(lemp->name,in,out,&lineno); /* Generate the include code, if any */ tplt_print(out,lemp,lemp->include,&lineno); if( mhflag ){ char *name = file_makename(lemp->outname, ".h"); fprintf(out,"#include \"%s\"\n", name); lineno++; free(name); } tplt_xfer(lemp->name,in,out,&lineno); /* Generate #includes for the header file */ if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; fprintf(out,"#include \n"); lineno++; fprintf(out,"#endif\n"); lineno++; } /* Generate #defines for all tokens */ if( mhflag ){ const char *prefix; fprintf(out,"#if INTERFACE\n"); lineno++; if( lemp->tokenprefix ) prefix = lemp->tokenprefix; else prefix = ""; for(i=1; interminal; i++){ fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); lineno++; } fprintf(out,"#endif\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate the defines */ fprintf(out,"#define YYCODETYPE %s\n", minimum_size_type(0, lemp->nsymbol+1)); lineno++; fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++; fprintf(out,"#define YYACTIONTYPE %s\n", minimum_size_type(0, lemp->nstate+lemp->nrule+5)); lineno++; if( lemp->wildcard ){ fprintf(out,"#define YYWILDCARD %d\n", lemp->wildcard->index); lineno++; } print_stack_union(out,lemp,&lineno,mhflag); fprintf(out, "#ifndef YYSTACKDEPTH\n"); lineno++; if( lemp->stacksize ){ fprintf(out,"#define YYSTACKDEPTH %s\n",lemp->stacksize); lineno++; }else{ fprintf(out,"#define YYSTACKDEPTH 100\n"); lineno++; } fprintf(out, "#endif\n"); lineno++; if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; } name = lemp->name ? lemp->name : "Parse"; if( lemp->arg && lemp->arg[0] ){ int i; i = lemonStrlen(lemp->arg); while( i>=1 && isspace(lemp->arg[i-1]) ) i--; while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--; fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++; fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++; fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n", name,lemp->arg,&lemp->arg[i]); lineno++; fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n", name,&lemp->arg[i],&lemp->arg[i]); lineno++; }else{ fprintf(out,"#define %sARG_SDECL\n",name); lineno++; fprintf(out,"#define %sARG_PDECL\n",name); lineno++; fprintf(out,"#define %sARG_FETCH\n",name); lineno++; fprintf(out,"#define %sARG_STORE\n",name); lineno++; } if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++; fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++; if( lemp->errsym->useCnt ){ fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++; fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++; } if( lemp->has_fallback ){ fprintf(out,"#define YYFALLBACK 1\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate the action table and its associates: ** ** yy_action[] A single table containing all actions. ** yy_lookahead[] A table containing the lookahead for each entry in ** yy_action. Used to detect hash collisions. ** yy_shift_ofst[] For each state, the offset into yy_action for ** shifting terminals. ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. */ /* Compute the actions on all states and count them up */ ax = (struct axset *) calloc(lemp->nstate*2, sizeof(ax[0])); if( ax==0 ){ fprintf(stderr,"malloc failed\n"); exit(1); } for(i=0; instate; i++){ stp = lemp->sorted[i]; ax[i*2].stp = stp; ax[i*2].isTkn = 1; ax[i*2].nAction = stp->nTknAct; ax[i*2+1].stp = stp; ax[i*2+1].isTkn = 0; ax[i*2+1].nAction = stp->nNtAct; } mxTknOfst = mnTknOfst = 0; mxNtOfst = mnNtOfst = 0; /* Compute the action table. In order to try to keep the size of the ** action table to a minimum, the heuristic of placing the largest action ** sets first is used. */ for(i=0; instate*2; i++) ax[i].iOrder = i; qsort(ax, lemp->nstate*2, sizeof(ax[0]), axset_compare); pActtab = acttab_alloc(); for(i=0; instate*2 && ax[i].nAction>0; i++){ stp = ax[i].stp; if( ax[i].isTkn ){ for(ap=stp->ap; ap; ap=ap->next){ int action; if( ap->sp->index>=lemp->nterminal ) continue; action = compute_action(lemp, ap); if( action<0 ) continue; acttab_action(pActtab, ap->sp->index, action); } stp->iTknOfst = acttab_insert(pActtab); if( stp->iTknOfstiTknOfst; if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst; }else{ for(ap=stp->ap; ap; ap=ap->next){ int action; if( ap->sp->indexnterminal ) continue; if( ap->sp->index==lemp->nsymbol ) continue; action = compute_action(lemp, ap); if( action<0 ) continue; acttab_action(pActtab, ap->sp->index, action); } stp->iNtOfst = acttab_insert(pActtab); if( stp->iNtOfstiNtOfst; if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst; } } free(ax); /* Output the yy_action table */ n = acttab_size(pActtab); fprintf(out,"#define YY_ACTTAB_COUNT (%d)\n", n); lineno++; fprintf(out,"static const YYACTIONTYPE yy_action[] = {\n"); lineno++; for(i=j=0; instate + lemp->nrule + 2; if( j==0 ) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", action); if( j==9 || i==n-1 ){ fprintf(out, "\n"); lineno++; j = 0; }else{ j++; } } fprintf(out, "};\n"); lineno++; /* Output the yy_lookahead table */ fprintf(out,"static const YYCODETYPE yy_lookahead[] = {\n"); lineno++; for(i=j=0; insymbol; if( j==0 ) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", la); if( j==9 || i==n-1 ){ fprintf(out, "\n"); lineno++; j = 0; }else{ j++; } } fprintf(out, "};\n"); lineno++; /* Output the yy_shift_ofst[] table */ fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++; n = lemp->nstate; while( n>0 && lemp->sorted[n-1]->iTknOfst==NO_OFFSET ) n--; fprintf(out, "#define YY_SHIFT_COUNT (%d)\n", n-1); lineno++; fprintf(out, "#define YY_SHIFT_MIN (%d)\n", mnTknOfst); lineno++; fprintf(out, "#define YY_SHIFT_MAX (%d)\n", mxTknOfst); lineno++; fprintf(out, "static const %s yy_shift_ofst[] = {\n", minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++; for(i=j=0; isorted[i]; ofst = stp->iTknOfst; if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1; if( j==0 ) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", ofst); if( j==9 || i==n-1 ){ fprintf(out, "\n"); lineno++; j = 0; }else{ j++; } } fprintf(out, "};\n"); lineno++; /* Output the yy_reduce_ofst[] table */ fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++; n = lemp->nstate; while( n>0 && lemp->sorted[n-1]->iNtOfst==NO_OFFSET ) n--; fprintf(out, "#define YY_REDUCE_COUNT (%d)\n", n-1); lineno++; fprintf(out, "#define YY_REDUCE_MIN (%d)\n", mnNtOfst); lineno++; fprintf(out, "#define YY_REDUCE_MAX (%d)\n", mxNtOfst); lineno++; fprintf(out, "static const %s yy_reduce_ofst[] = {\n", minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++; for(i=j=0; isorted[i]; ofst = stp->iNtOfst; if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1; if( j==0 ) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", ofst); if( j==9 || i==n-1 ){ fprintf(out, "\n"); lineno++; j = 0; }else{ j++; } } fprintf(out, "};\n"); lineno++; /* Output the default action table */ fprintf(out, "static const YYACTIONTYPE yy_default[] = {\n"); lineno++; n = lemp->nstate; for(i=j=0; isorted[i]; if( j==0 ) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", stp->iDflt); if( j==9 || i==n-1 ){ fprintf(out, "\n"); lineno++; j = 0; }else{ j++; } } fprintf(out, "};\n"); lineno++; tplt_xfer(lemp->name,in,out,&lineno); /* Generate the table of fallback tokens. */ if( lemp->has_fallback ){ int mx = lemp->nterminal - 1; while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; } for(i=0; i<=mx; i++){ struct symbol *p = lemp->symbols[i]; if( p->fallback==0 ){ fprintf(out, " 0, /* %10s => nothing */\n", p->name); }else{ fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index, p->name, p->fallback->name); } lineno++; } } tplt_xfer(lemp->name, in, out, &lineno); /* Generate a table containing the symbolic name of every symbol */ for(i=0; insymbol; i++){ sprintf(line,"\"%s\",",lemp->symbols[i]->name); fprintf(out," %-15s",line); if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } } if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate a table containing a text string that describes every ** rule in the rule set of the grammar. This information is used ** when tracing REDUCE actions. */ for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ assert( rp->index==i ); fprintf(out," /* %3d */ \"", i); writeRuleText(out, rp); fprintf(out,"\",\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes every time a symbol is popped from ** the stack while processing errors or while destroying the parser. ** (In other words, generate the %destructor actions) */ if( lemp->tokendest ){ int once = 1; for(i=0; insymbol; i++){ struct symbol *sp = lemp->symbols[i]; if( sp==0 || sp->type!=TERMINAL ) continue; if( once ){ fprintf(out, " /* TERMINAL Destructor */\n"); lineno++; once = 0; } fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++; } for(i=0; insymbol && lemp->symbols[i]->type!=TERMINAL; i++); if( insymbol ){ emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); fprintf(out," break;\n"); lineno++; } } if( lemp->vardest ){ struct symbol *dflt_sp = 0; int once = 1; for(i=0; insymbol; i++){ struct symbol *sp = lemp->symbols[i]; if( sp==0 || sp->type==TERMINAL || sp->index<=0 || sp->destructor!=0 ) continue; if( once ){ fprintf(out, " /* Default NON-TERMINAL Destructor */\n"); lineno++; once = 0; } fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++; dflt_sp = sp; } if( dflt_sp!=0 ){ emit_destructor_code(out,dflt_sp,lemp,&lineno); } fprintf(out," break;\n"); lineno++; } for(i=0; insymbol; i++){ struct symbol *sp = lemp->symbols[i]; if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue; fprintf(out," case %d: /* %s */\n", sp->index, sp->name); lineno++; /* Combine duplicate destructors into a single case */ for(j=i+1; jnsymbol; j++){ struct symbol *sp2 = lemp->symbols[j]; if( sp2 && sp2->type!=TERMINAL && sp2->destructor && sp2->dtnum==sp->dtnum && strcmp(sp->destructor,sp2->destructor)==0 ){ fprintf(out," case %d: /* %s */\n", sp2->index, sp2->name); lineno++; sp2->destructor = 0; } } emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); fprintf(out," break;\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes whenever the parser stack overflows */ tplt_print(out,lemp,lemp->overflow,&lineno); tplt_xfer(lemp->name,in,out,&lineno); /* Generate the table of rule information ** ** Note: This code depends on the fact that rules are number ** sequentually beginning with 0. */ for(rp=lemp->rule; rp; rp=rp->next){ fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which execution during each REDUCE action */ for(rp=lemp->rule; rp; rp=rp->next){ translate_code(lemp, rp); } /* First output rules other than the default: rule */ for(rp=lemp->rule; rp; rp=rp->next){ struct rule *rp2; /* Other rules with the same action */ if( rp->code==0 ) continue; if( rp->code[0]=='\n' && rp->code[1]==0 ) continue; /* Will be default: */ fprintf(out," case %d: /* ", rp->index); writeRuleText(out, rp); fprintf(out, " */\n"); lineno++; for(rp2=rp->next; rp2; rp2=rp2->next){ if( rp2->code==rp->code ){ fprintf(out," case %d: /* ", rp2->index); writeRuleText(out, rp2); fprintf(out," */ yytestcase(yyruleno==%d);\n", rp2->index); lineno++; rp2->code = 0; } } emit_code(out,rp,lemp,&lineno); fprintf(out," break;\n"); lineno++; rp->code = 0; } /* Finally, output the default: rule. We choose as the default: all ** empty actions. */ fprintf(out," default:\n"); lineno++; for(rp=lemp->rule; rp; rp=rp->next){ if( rp->code==0 ) continue; assert( rp->code[0]=='\n' && rp->code[1]==0 ); fprintf(out," /* (%d) ", rp->index); writeRuleText(out, rp); fprintf(out, " */ yytestcase(yyruleno==%d);\n", rp->index); lineno++; } fprintf(out," break;\n"); lineno++; tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes if a parse fails */ tplt_print(out,lemp,lemp->failure,&lineno); tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes when a syntax error occurs */ tplt_print(out,lemp,lemp->error,&lineno); tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes when the parser accepts its input */ tplt_print(out,lemp,lemp->accept,&lineno); tplt_xfer(lemp->name,in,out,&lineno); /* Append any addition code the user desires */ tplt_print(out,lemp,lemp->extracode,&lineno); fclose(in); fclose(out); return; } /* Generate a header file for the parser */ void ReportHeader(struct lemon *lemp) { FILE *out, *in; const char *prefix; char line[LINESIZE]; char pattern[LINESIZE]; int i; if( lemp->tokenprefix ) prefix = lemp->tokenprefix; else prefix = ""; in = file_open(lemp,".h","rb"); if( in ){ for(i=1; interminal && fgets(line,LINESIZE,in); i++){ sprintf(pattern,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); if( strcmp(line,pattern) ) break; } fclose(in); if( i==lemp->nterminal ){ /* No change in the file. Don't rewrite it. */ return; } } out = file_open(lemp,".h","wb"); if( out ){ for(i=1; interminal; i++){ fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); } fclose(out); } return; } /* Reduce the size of the action tables, if possible, by making use ** of defaults. ** ** In this version, we take the most frequent REDUCE action and make ** it the default. Except, there is no default if the wildcard token ** is a possible look-ahead. */ void CompressTables(struct lemon *lemp) { struct state *stp; struct action *ap, *ap2; struct rule *rp, *rp2, *rbest; int nbest, n; int i; int usesWildcard; for(i=0; instate; i++){ stp = lemp->sorted[i]; nbest = 0; rbest = 0; usesWildcard = 0; for(ap=stp->ap; ap; ap=ap->next){ if( ap->type==SHIFT && ap->sp==lemp->wildcard ){ usesWildcard = 1; } if( ap->type!=REDUCE ) continue; rp = ap->x.rp; if( rp->lhsStart ) continue; if( rp==rbest ) continue; n = 1; for(ap2=ap->next; ap2; ap2=ap2->next){ if( ap2->type!=REDUCE ) continue; rp2 = ap2->x.rp; if( rp2==rbest ) continue; if( rp2==rp ) n++; } if( n>nbest ){ nbest = n; rbest = rp; } } /* Do not make a default if the number of rules to default ** is not at least 1 or if the wildcard token is a possible ** lookahead. */ if( nbest<1 || usesWildcard ) continue; /* Combine matching REDUCE actions into a single default */ for(ap=stp->ap; ap; ap=ap->next){ if( ap->type==REDUCE && ap->x.rp==rbest ) break; } assert( ap ); ap->sp = Symbol_new("{default}"); for(ap=ap->next; ap; ap=ap->next){ if( ap->type==REDUCE && ap->x.rp==rbest ) ap->type = NOT_USED; } stp->ap = Action_sort(stp->ap); } } /* ** Compare two states for sorting purposes. The smaller state is the ** one with the most non-terminal actions. If they have the same number ** of non-terminal actions, then the smaller is the one with the most ** token actions. */ static int stateResortCompare(const void *a, const void *b){ const struct state *pA = *(const struct state**)a; const struct state *pB = *(const struct state**)b; int n; n = pB->nNtAct - pA->nNtAct; if( n==0 ){ n = pB->nTknAct - pA->nTknAct; if( n==0 ){ n = pB->statenum - pA->statenum; } } assert( n!=0 ); return n; } /* ** Renumber and resort states so that states with fewer choices ** occur at the end. Except, keep state 0 as the first state. */ void ResortStates(struct lemon *lemp) { int i; struct state *stp; struct action *ap; for(i=0; instate; i++){ stp = lemp->sorted[i]; stp->nTknAct = stp->nNtAct = 0; stp->iDflt = lemp->nstate + lemp->nrule; stp->iTknOfst = NO_OFFSET; stp->iNtOfst = NO_OFFSET; for(ap=stp->ap; ap; ap=ap->next){ if( compute_action(lemp,ap)>=0 ){ if( ap->sp->indexnterminal ){ stp->nTknAct++; }else if( ap->sp->indexnsymbol ){ stp->nNtAct++; }else{ stp->iDflt = compute_action(lemp, ap); } } } } qsort(&lemp->sorted[1], lemp->nstate-1, sizeof(lemp->sorted[0]), stateResortCompare); for(i=0; instate; i++){ lemp->sorted[i]->statenum = i; } } /***************** From the file "set.c" ************************************/ /* ** Set manipulation routines for the LEMON parser generator. */ static int size = 0; /* Set the set size */ void SetSize(int n) { size = n+1; } /* Allocate a new set */ char *SetNew(){ char *s; s = (char*)calloc( size, 1); if( s==0 ){ extern void memory_error(); memory_error(); } return s; } /* Deallocate a set */ void SetFree(char *s) { free(s); } /* Add a new element to the set. Return TRUE if the element was added ** and FALSE if it was already there. */ int SetAdd(char *s, int e) { int rv; assert( e>=0 && esize = 1024; x1a->count = 0; x1a->tbl = (x1node*)malloc( (sizeof(x1node) + sizeof(x1node*))*1024 ); if( x1a->tbl==0 ){ free(x1a); x1a = 0; }else{ int i; x1a->ht = (x1node**)&(x1a->tbl[1024]); for(i=0; i<1024; i++) x1a->ht[i] = 0; } } } /* Insert a new record into the array. Return TRUE if successful. ** Prior data with the same key is NOT overwritten */ int Strsafe_insert(const char *data) { x1node *np; int h; int ph; if( x1a==0 ) return 0; ph = strhash(data); h = ph & (x1a->size-1); np = x1a->ht[h]; while( np ){ if( strcmp(np->data,data)==0 ){ /* An existing entry with the same key is found. */ /* Fail because overwrite is not allows. */ return 0; } np = np->next; } if( x1a->count>=x1a->size ){ /* Need to make the hash table bigger */ int i,size; struct s_x1 array; array.size = size = x1a->size*2; array.count = x1a->count; array.tbl = (x1node*)malloc( (sizeof(x1node) + sizeof(x1node*))*size ); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x1node**)&(array.tbl[size]); for(i=0; icount; i++){ x1node *oldnp, *newnp; oldnp = &(x1a->tbl[i]); h = strhash(oldnp->data) & (size-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } free(x1a->tbl); *x1a = array; } /* Insert the new data */ h = ph & (x1a->size-1); np = &(x1a->tbl[x1a->count++]); np->data = data; if( x1a->ht[h] ) x1a->ht[h]->from = &(np->next); np->next = x1a->ht[h]; x1a->ht[h] = np; np->from = &(x1a->ht[h]); return 1; } /* Return a pointer to data assigned to the given key. Return NULL ** if no such key. */ const char *Strsafe_find(const char *key) { int h; x1node *np; if( x1a==0 ) return 0; h = strhash(key) & (x1a->size-1); np = x1a->ht[h]; while( np ){ if( strcmp(np->data,key)==0 ) break; np = np->next; } return np ? np->data : 0; } /* Return a pointer to the (terminal or nonterminal) symbol "x". ** Create a new symbol if this is the first time "x" has been seen. */ struct symbol *Symbol_new(const char *x) { struct symbol *sp; sp = Symbol_find(x); if( sp==0 ){ sp = (struct symbol *)calloc(1, sizeof(struct symbol) ); MemoryCheck(sp); sp->name = Strsafe(x); sp->type = isupper(*x) ? TERMINAL : NONTERMINAL; sp->rule = 0; sp->fallback = 0; sp->prec = -1; sp->assoc = UNK; sp->firstset = 0; sp->lambda = LEMON_FALSE; sp->destructor = 0; sp->destLineno = 0; sp->datatype = 0; sp->useCnt = 0; Symbol_insert(sp,sp->name); } sp->useCnt++; return sp; } /* Compare two symbols for working purposes ** ** Symbols that begin with upper case letters (terminals or tokens) ** must sort before symbols that begin with lower case letters ** (non-terminals). Other than that, the order does not matter. ** ** We find experimentally that leaving the symbols in their original ** order (the order they appeared in the grammar file) gives the ** smallest parser tables in SQLite. */ int Symbolcmpp(const void *_a, const void *_b) { const struct symbol **a = (const struct symbol **) _a; const struct symbol **b = (const struct symbol **) _b; int i1 = (**a).index + 10000000*((**a).name[0]>'Z'); int i2 = (**b).index + 10000000*((**b).name[0]>'Z'); assert( i1!=i2 || strcmp((**a).name,(**b).name)==0 ); return i1-i2; } /* There is one instance of the following structure for each ** associative array of type "x2". */ struct s_x2 { int size; /* The number of available slots. */ /* Must be a power of 2 greater than or */ /* equal to 1 */ int count; /* Number of currently slots filled */ struct s_x2node *tbl; /* The data stored here */ struct s_x2node **ht; /* Hash table for lookups */ }; /* There is one instance of this structure for every data element ** in an associative array of type "x2". */ typedef struct s_x2node { struct symbol *data; /* The data */ const char *key; /* The key */ struct s_x2node *next; /* Next entry with the same hash */ struct s_x2node **from; /* Previous link */ } x2node; /* There is only one instance of the array, which is the following */ static struct s_x2 *x2a; /* Allocate a new associative array */ void Symbol_init(){ if( x2a ) return; x2a = (struct s_x2*)malloc( sizeof(struct s_x2) ); if( x2a ){ x2a->size = 128; x2a->count = 0; x2a->tbl = (x2node*)malloc( (sizeof(x2node) + sizeof(x2node*))*128 ); if( x2a->tbl==0 ){ free(x2a); x2a = 0; }else{ int i; x2a->ht = (x2node**)&(x2a->tbl[128]); for(i=0; i<128; i++) x2a->ht[i] = 0; } } } /* Insert a new record into the array. Return TRUE if successful. ** Prior data with the same key is NOT overwritten */ int Symbol_insert(struct symbol *data, const char *key) { x2node *np; int h; int ph; if( x2a==0 ) return 0; ph = strhash(key); h = ph & (x2a->size-1); np = x2a->ht[h]; while( np ){ if( strcmp(np->key,key)==0 ){ /* An existing entry with the same key is found. */ /* Fail because overwrite is not allows. */ return 0; } np = np->next; } if( x2a->count>=x2a->size ){ /* Need to make the hash table bigger */ int i,size; struct s_x2 array; array.size = size = x2a->size*2; array.count = x2a->count; array.tbl = (x2node*)malloc( (sizeof(x2node) + sizeof(x2node*))*size ); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x2node**)&(array.tbl[size]); for(i=0; icount; i++){ x2node *oldnp, *newnp; oldnp = &(x2a->tbl[i]); h = strhash(oldnp->key) & (size-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; newnp->key = oldnp->key; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } free(x2a->tbl); *x2a = array; } /* Insert the new data */ h = ph & (x2a->size-1); np = &(x2a->tbl[x2a->count++]); np->key = key; np->data = data; if( x2a->ht[h] ) x2a->ht[h]->from = &(np->next); np->next = x2a->ht[h]; x2a->ht[h] = np; np->from = &(x2a->ht[h]); return 1; } /* Return a pointer to data assigned to the given key. Return NULL ** if no such key. */ struct symbol *Symbol_find(const char *key) { int h; x2node *np; if( x2a==0 ) return 0; h = strhash(key) & (x2a->size-1); np = x2a->ht[h]; while( np ){ if( strcmp(np->key,key)==0 ) break; np = np->next; } return np ? np->data : 0; } /* Return the n-th data. Return NULL if n is out of range. */ struct symbol *Symbol_Nth(int n) { struct symbol *data; if( x2a && n>0 && n<=x2a->count ){ data = x2a->tbl[n-1].data; }else{ data = 0; } return data; } /* Return the size of the array */ int Symbol_count() { return x2a ? x2a->count : 0; } /* Return an array of pointers to all data in the table. ** The array is obtained from malloc. Return NULL if memory allocation ** problems, or if the array is empty. */ struct symbol **Symbol_arrayof() { struct symbol **array; int i,size; if( x2a==0 ) return 0; size = x2a->count; array = (struct symbol **)calloc(size, sizeof(struct symbol *)); if( array ){ for(i=0; itbl[i].data; } return array; } /* Compare two configurations */ int Configcmp(const char *_a,const char *_b) { const struct config *a = (struct config *) _a; const struct config *b = (struct config *) _b; int x; x = a->rp->index - b->rp->index; if( x==0 ) x = a->dot - b->dot; return x; } /* Compare two states */ PRIVATE int statecmp(struct config *a, struct config *b) { int rc; for(rc=0; rc==0 && a && b; a=a->bp, b=b->bp){ rc = a->rp->index - b->rp->index; if( rc==0 ) rc = a->dot - b->dot; } if( rc==0 ){ if( a ) rc = 1; if( b ) rc = -1; } return rc; } /* Hash a state */ PRIVATE int statehash(struct config *a) { int h=0; while( a ){ h = h*571 + a->rp->index*37 + a->dot; a = a->bp; } return h; } /* Allocate a new state structure */ struct state *State_new() { struct state *newstate; newstate = (struct state *)calloc(1, sizeof(struct state) ); MemoryCheck(newstate); return newstate; } /* There is one instance of the following structure for each ** associative array of type "x3". */ struct s_x3 { int size; /* The number of available slots. */ /* Must be a power of 2 greater than or */ /* equal to 1 */ int count; /* Number of currently slots filled */ struct s_x3node *tbl; /* The data stored here */ struct s_x3node **ht; /* Hash table for lookups */ }; /* There is one instance of this structure for every data element ** in an associative array of type "x3". */ typedef struct s_x3node { struct state *data; /* The data */ struct config *key; /* The key */ struct s_x3node *next; /* Next entry with the same hash */ struct s_x3node **from; /* Previous link */ } x3node; /* There is only one instance of the array, which is the following */ static struct s_x3 *x3a; /* Allocate a new associative array */ void State_init(){ if( x3a ) return; x3a = (struct s_x3*)malloc( sizeof(struct s_x3) ); if( x3a ){ x3a->size = 128; x3a->count = 0; x3a->tbl = (x3node*)malloc( (sizeof(x3node) + sizeof(x3node*))*128 ); if( x3a->tbl==0 ){ free(x3a); x3a = 0; }else{ int i; x3a->ht = (x3node**)&(x3a->tbl[128]); for(i=0; i<128; i++) x3a->ht[i] = 0; } } } /* Insert a new record into the array. Return TRUE if successful. ** Prior data with the same key is NOT overwritten */ int State_insert(struct state *data, struct config *key) { x3node *np; int h; int ph; if( x3a==0 ) return 0; ph = statehash(key); h = ph & (x3a->size-1); np = x3a->ht[h]; while( np ){ if( statecmp(np->key,key)==0 ){ /* An existing entry with the same key is found. */ /* Fail because overwrite is not allows. */ return 0; } np = np->next; } if( x3a->count>=x3a->size ){ /* Need to make the hash table bigger */ int i,size; struct s_x3 array; array.size = size = x3a->size*2; array.count = x3a->count; array.tbl = (x3node*)malloc( (sizeof(x3node) + sizeof(x3node*))*size ); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x3node**)&(array.tbl[size]); for(i=0; icount; i++){ x3node *oldnp, *newnp; oldnp = &(x3a->tbl[i]); h = statehash(oldnp->key) & (size-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; newnp->key = oldnp->key; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } free(x3a->tbl); *x3a = array; } /* Insert the new data */ h = ph & (x3a->size-1); np = &(x3a->tbl[x3a->count++]); np->key = key; np->data = data; if( x3a->ht[h] ) x3a->ht[h]->from = &(np->next); np->next = x3a->ht[h]; x3a->ht[h] = np; np->from = &(x3a->ht[h]); return 1; } /* Return a pointer to data assigned to the given key. Return NULL ** if no such key. */ struct state *State_find(struct config *key) { int h; x3node *np; if( x3a==0 ) return 0; h = statehash(key) & (x3a->size-1); np = x3a->ht[h]; while( np ){ if( statecmp(np->key,key)==0 ) break; np = np->next; } return np ? np->data : 0; } /* Return an array of pointers to all data in the table. ** The array is obtained from malloc. Return NULL if memory allocation ** problems, or if the array is empty. */ struct state **State_arrayof() { struct state **array; int i,size; if( x3a==0 ) return 0; size = x3a->count; array = (struct state **)malloc( sizeof(struct state *)*size ); if( array ){ for(i=0; itbl[i].data; } return array; } /* Hash a configuration */ PRIVATE int confighash(struct config *a) { int h=0; h = h*571 + a->rp->index*37 + a->dot; return h; } /* There is one instance of the following structure for each ** associative array of type "x4". */ struct s_x4 { int size; /* The number of available slots. */ /* Must be a power of 2 greater than or */ /* equal to 1 */ int count; /* Number of currently slots filled */ struct s_x4node *tbl; /* The data stored here */ struct s_x4node **ht; /* Hash table for lookups */ }; /* There is one instance of this structure for every data element ** in an associative array of type "x4". */ typedef struct s_x4node { struct config *data; /* The data */ struct s_x4node *next; /* Next entry with the same hash */ struct s_x4node **from; /* Previous link */ } x4node; /* There is only one instance of the array, which is the following */ static struct s_x4 *x4a; /* Allocate a new associative array */ void Configtable_init(){ if( x4a ) return; x4a = (struct s_x4*)malloc( sizeof(struct s_x4) ); if( x4a ){ x4a->size = 64; x4a->count = 0; x4a->tbl = (x4node*)malloc( (sizeof(x4node) + sizeof(x4node*))*64 ); if( x4a->tbl==0 ){ free(x4a); x4a = 0; }else{ int i; x4a->ht = (x4node**)&(x4a->tbl[64]); for(i=0; i<64; i++) x4a->ht[i] = 0; } } } /* Insert a new record into the array. Return TRUE if successful. ** Prior data with the same key is NOT overwritten */ int Configtable_insert(struct config *data) { x4node *np; int h; int ph; if( x4a==0 ) return 0; ph = confighash(data); h = ph & (x4a->size-1); np = x4a->ht[h]; while( np ){ if( Configcmp((const char *) np->data,(const char *) data)==0 ){ /* An existing entry with the same key is found. */ /* Fail because overwrite is not allows. */ return 0; } np = np->next; } if( x4a->count>=x4a->size ){ /* Need to make the hash table bigger */ int i,size; struct s_x4 array; array.size = size = x4a->size*2; array.count = x4a->count; array.tbl = (x4node*)malloc( (sizeof(x4node) + sizeof(x4node*))*size ); if( array.tbl==0 ) return 0; /* Fail due to malloc failure */ array.ht = (x4node**)&(array.tbl[size]); for(i=0; icount; i++){ x4node *oldnp, *newnp; oldnp = &(x4a->tbl[i]); h = confighash(oldnp->data) & (size-1); newnp = &(array.tbl[i]); if( array.ht[h] ) array.ht[h]->from = &(newnp->next); newnp->next = array.ht[h]; newnp->data = oldnp->data; newnp->from = &(array.ht[h]); array.ht[h] = newnp; } free(x4a->tbl); *x4a = array; } /* Insert the new data */ h = ph & (x4a->size-1); np = &(x4a->tbl[x4a->count++]); np->data = data; if( x4a->ht[h] ) x4a->ht[h]->from = &(np->next); np->next = x4a->ht[h]; x4a->ht[h] = np; np->from = &(x4a->ht[h]); return 1; } /* Return a pointer to data assigned to the given key. Return NULL ** if no such key. */ struct config *Configtable_find(struct config *key) { int h; x4node *np; if( x4a==0 ) return 0; h = confighash(key) & (x4a->size-1); np = x4a->ht[h]; while( np ){ if( Configcmp((const char *) np->data,(const char *) key)==0 ) break; np = np->next; } return np ? np->data : 0; } /* Remove all data from the table. Pass each data to the function "f" ** as it is removed. ("f" may be null to avoid this step.) */ void Configtable_clear(int(*f)(struct config *)) { int i; if( x4a==0 || x4a->count==0 ) return; if( f ) for(i=0; icount; i++) (*f)(x4a->tbl[i].data); for(i=0; isize; i++) x4a->ht[i] = 0; x4a->count = 0; return; } openvpn-auth-ldap-auth-ldap-2.0.4/tools/lempar.c000066400000000000000000000662211332642612100215270ustar00rootroot00000000000000/* Driver template for the LEMON parser generator. ** The author disclaims copyright to this source code. */ /* First off, code is included that follows the "include" declaration ** in the input grammar file. */ #include #include %% /* Next is all token values, in a form suitable for use by makeheaders. ** This section will be null unless lemon is run with the -m switch. */ /* ** These constants (all generated automatically by the parser generator) ** specify the various kinds of tokens (terminals) that the parser ** understands. ** ** Each symbol here is a terminal symbol in the grammar. */ %% /* Make sure the INTERFACE macro is defined. */ #ifndef INTERFACE # define INTERFACE 1 #endif /* The next thing included is series of defines which control ** various aspects of the generated parser. ** YYCODETYPE is the data type used for storing terminal ** and nonterminal numbers. "unsigned char" is ** used if there are fewer than 250 terminals ** and nonterminals. "int" is used otherwise. ** YYNOCODE is a number of type YYCODETYPE which corresponds ** to no legal terminal or nonterminal number. This ** number is used to fill in empty slots of the hash ** table. ** YYFALLBACK If defined, this indicates that one or more tokens ** have fall-back values which should be used if the ** original value of the token will not parse. ** YYACTIONTYPE is the data type used for storing terminal ** and nonterminal numbers. "unsigned char" is ** used if there are fewer than 250 rules and ** states combined. "int" is used otherwise. ** ParseTOKENTYPE is the data type used for minor tokens given ** directly to the parser from the tokenizer. ** YYMINORTYPE is the data type used for all minor tokens. ** This is typically a union of many types, one of ** which is ParseTOKENTYPE. The entry in the union ** for base tokens is called "yy0". ** YYSTACKDEPTH is the maximum depth of the parser's stack. If ** zero the stack is dynamically sized using realloc() ** ParseARG_SDECL A static variable declaration for the %extra_argument ** ParseARG_PDECL A parameter declaration for the %extra_argument ** ParseARG_STORE Code to store %extra_argument into yypParser ** ParseARG_FETCH Code to extract %extra_argument from yypParser ** YYNSTATE the combined number of states. ** YYNRULE the number of rules in the grammar ** YYERRORSYMBOL is the code number of the error symbol. If not ** defined, then do no error processing. */ %% #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) #define YY_ERROR_ACTION (YYNSTATE+YYNRULE) /* The yyzerominor constant is used to initialize instances of ** YYMINORTYPE objects to zero. */ static const YYMINORTYPE yyzerominor = { 0 }; /* Define the yytestcase() macro to be a no-op if is not already defined ** otherwise. ** ** Applications can choose to define yytestcase() in the %include section ** to a macro that can assist in verifying code coverage. For production ** code the yytestcase() macro should be turned off. But it is useful ** for testing. */ #ifndef yytestcase # define yytestcase(X) #endif /* Next are the tables used to determine what action to take based on the ** current state and lookahead token. These tables are used to implement ** functions that take a state number and lookahead value and return an ** action integer. ** ** Suppose the action integer is N. Then the action is determined as ** follows ** ** 0 <= N < YYNSTATE Shift N. That is, push the lookahead ** token onto the stack and goto state N. ** ** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE. ** ** N == YYNSTATE+YYNRULE A syntax error has occurred. ** ** N == YYNSTATE+YYNRULE+1 The parser accepts its input. ** ** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused ** slots in the yy_action[] table. ** ** The action table is constructed as a single large table named yy_action[]. ** Given state S and lookahead X, the action is computed as ** ** yy_action[ yy_shift_ofst[S] + X ] ** ** If the index value yy_shift_ofst[S]+X is out of range or if the value ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table ** and that yy_default[S] should be used instead. ** ** The formula above is for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after ** a reduce action) then the yy_reduce_ofst[] array is used in place of ** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of ** YY_SHIFT_USE_DFLT. ** ** The following are the tables generated in this section: ** ** yy_action[] A single table containing all actions. ** yy_lookahead[] A table containing the lookahead for each entry in ** yy_action. Used to detect hash collisions. ** yy_shift_ofst[] For each state, the offset into yy_action for ** shifting terminals. ** yy_reduce_ofst[] For each state, the offset into yy_action for ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. */ %% /* The next table maps tokens into fallback tokens. If a construct ** like the following: ** ** %fallback ID X Y Z. ** ** appears in the grammar, then ID becomes a fallback token for X, Y, ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser ** but it does not parse, the type of the token is changed to ID and ** the parse is retried before an error is thrown. */ #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { %% }; #endif /* YYFALLBACK */ /* The following structure represents a single element of the ** parser's stack. Information stored includes: ** ** + The state number for the parser at this level of the stack. ** ** + The value of the token stored at this level of the stack. ** (In other words, the "major" token.) ** ** + The semantic value stored at this level of the stack. This is ** the information used by the action routines in the grammar. ** It is sometimes called the "minor" token. */ struct yyStackEntry { YYACTIONTYPE stateno; /* The state-number */ YYCODETYPE major; /* The major token value. This is the code ** number for the token at this stack level */ YYMINORTYPE minor; /* The user-supplied minor token value. This ** is the value of the token */ }; typedef struct yyStackEntry yyStackEntry; /* The state of the parser is completely contained in an instance of ** the following structure */ struct yyParser { int yyidx; /* Index of top element in stack */ #ifdef YYTRACKMAXSTACKDEPTH int yyidxMax; /* Maximum value of yyidx */ #endif int yyerrcnt; /* Shifts left before out of the error */ ParseARG_SDECL /* A place to hold %extra_argument */ #if YYSTACKDEPTH<=0 int yystksz; /* Current side of the stack */ yyStackEntry *yystack; /* The parser's stack */ #else yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ #endif }; typedef struct yyParser yyParser; #ifndef NDEBUG #include static FILE *yyTraceFILE = 0; static char *yyTracePrompt = 0; #endif /* NDEBUG */ #ifndef NDEBUG /* ** Turn parser tracing on by giving a stream to which to write the trace ** and a prompt to preface each trace message. Tracing is turned off ** by making either argument NULL ** ** Inputs: **
    **
  • A FILE* to which trace output should be written. ** If NULL, then tracing is turned off. **
  • A prefix string written at the beginning of every ** line of trace output. If NULL, then tracing is ** turned off. **
** ** Outputs: ** None. */ void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ yyTraceFILE = TraceFILE; yyTracePrompt = zTracePrompt; if( yyTraceFILE==0 ) yyTracePrompt = 0; else if( yyTracePrompt==0 ) yyTraceFILE = 0; } #endif /* NDEBUG */ #ifndef NDEBUG /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *const yyTokenName[] = { %% }; #endif /* NDEBUG */ #ifndef NDEBUG /* For tracing reduce actions, the names of all rules are required. */ static const char *const yyRuleName[] = { %% }; #endif /* NDEBUG */ #if YYSTACKDEPTH<=0 /* ** Try to increase the size of the parser stack. */ static void yyGrowStack(yyParser *p){ int newSize; yyStackEntry *pNew; newSize = p->yystksz*2 + 100; pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); if( pNew ){ p->yystack = pNew; p->yystksz = newSize; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack grows to %d entries!\n", yyTracePrompt, p->yystksz); } #endif } } #endif /* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. ** ** Inputs: ** A pointer to the function used to allocate memory. ** ** Outputs: ** A pointer to a parser. This pointer is used in subsequent calls ** to Parse and ParseFree. */ void *ParseAlloc(void *(*mallocProc)(size_t)){ yyParser *pParser; pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); if( pParser ){ pParser->yyidx = -1; #ifdef YYTRACKMAXSTACKDEPTH pParser->yyidxMax = 0; #endif #if YYSTACKDEPTH<=0 pParser->yystack = NULL; pParser->yystksz = 0; yyGrowStack(pParser); #endif } return pParser; } /* The following function deletes the value associated with a ** symbol. The symbol can be either a terminal or nonterminal. ** "yymajor" is the symbol code, and "yypminor" is a pointer to ** the value. */ static void yy_destructor( yyParser *yypParser, /* The parser */ YYCODETYPE yymajor, /* Type code for object to destroy */ YYMINORTYPE *yypminor /* The object to be destroyed */ ){ ParseARG_FETCH; switch( yymajor ){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen ** when the symbol is popped from the stack during a ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those ** which appear on the RHS of the rule, but which are not used ** inside the C code. */ %% default: break; /* If no destructor action specified: do nothing */ } } /* ** Pop the parser's stack once. ** ** If there is a destructor routine associated with the token which ** is popped from the stack, then call it. ** ** Return the major token number for the symbol popped. */ static int yy_pop_parser_stack(yyParser *pParser){ YYCODETYPE yymajor; yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; if( pParser->yyidx<0 ) return 0; #ifndef NDEBUG if( yyTraceFILE && pParser->yyidx>=0 ){ fprintf(yyTraceFILE,"%sPopping %s\n", yyTracePrompt, yyTokenName[yytos->major]); } #endif yymajor = yytos->major; yy_destructor(pParser, yymajor, &yytos->minor); pParser->yyidx--; return yymajor; } /* ** Deallocate and destroy a parser. Destructors are all called for ** all stack elements before shutting the parser down. ** ** Inputs: **
    **
  • A pointer to the parser. This should be a pointer ** obtained from ParseAlloc. **
  • A pointer to a function used to reclaim memory obtained ** from malloc. **
*/ void ParseFree( void *p, /* The parser to be deleted */ void (*freeProc)(void*) /* Function used to reclaim memory */ ){ yyParser *pParser = (yyParser*)p; if( pParser==0 ) return; while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); #if YYSTACKDEPTH<=0 free(pParser->yystack); #endif (*freeProc)((void*)pParser); } /* ** Return the peak depth of the stack for a parser. */ #ifdef YYTRACKMAXSTACKDEPTH int ParseStackPeak(void *p){ yyParser *pParser = (yyParser*)p; return pParser->yyidxMax; } #endif /* ** Find the appropriate action for a parser given the terminal ** look-ahead token iLookAhead. ** ** If the look-ahead token is YYNOCODE, then check to see if the action is ** independent of the look-ahead. If it is, return the action, otherwise ** return YY_NO_ACTION. */ static int yy_find_shift_action( yyParser *pParser, /* The parser */ YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; if( stateno>YY_SHIFT_COUNT || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){ return yy_default[stateno]; } assert( iLookAhead!=YYNOCODE ); i += iLookAhead; if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ if( iLookAhead>0 ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ if( iLookAhead %s\n", yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); } #endif return yy_find_shift_action(pParser, iFallback); } #endif #ifdef YYWILDCARD { int j = i - iLookAhead + YYWILDCARD; if( #if YY_SHIFT_MIN+YYWILDCARD<0 j>=0 && #endif #if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT j %s\n", yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); } #endif /* NDEBUG */ return yy_action[j]; } } #endif /* YYWILDCARD */ } return yy_default[stateno]; }else{ return yy_action[i]; } } /* ** Find the appropriate action for a parser given the non-terminal ** look-ahead token iLookAhead. ** ** If the look-ahead token is YYNOCODE, then check to see if the action is ** independent of the look-ahead. If it is, return the action, otherwise ** return YY_NO_ACTION. */ static int yy_find_reduce_action( int stateno, /* Current state number */ YYCODETYPE iLookAhead /* The look-ahead token */ ){ int i; #ifdef YYERRORSYMBOL if( stateno>YY_REDUCE_COUNT ){ return yy_default[stateno]; } #else assert( stateno<=YY_REDUCE_COUNT ); #endif i = yy_reduce_ofst[stateno]; assert( i!=YY_REDUCE_USE_DFLT ); assert( iLookAhead!=YYNOCODE ); i += iLookAhead; #ifdef YYERRORSYMBOL if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ return yy_default[stateno]; } #else assert( i>=0 && iyyidx--; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); } #endif while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will execute if the parser ** stack every overflows */ %% ParseARG_STORE; /* Suppress warning about unused %extra_argument var */ } /* ** Perform a shift action. */ static void yy_shift( yyParser *yypParser, /* The parser to be shifted */ int yyNewState, /* The new state to shift in */ int yyMajor, /* The major token to shift in */ YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */ ){ yyStackEntry *yytos; yypParser->yyidx++; #ifdef YYTRACKMAXSTACKDEPTH if( yypParser->yyidx>yypParser->yyidxMax ){ yypParser->yyidxMax = yypParser->yyidx; } #endif #if YYSTACKDEPTH>0 if( yypParser->yyidx>=YYSTACKDEPTH ){ yyStackOverflow(yypParser, yypMinor); return; } #else if( yypParser->yyidx>=yypParser->yystksz ){ yyGrowStack(yypParser); if( yypParser->yyidx>=yypParser->yystksz ){ yyStackOverflow(yypParser, yypMinor); return; } } #endif yytos = &yypParser->yystack[yypParser->yyidx]; yytos->stateno = (YYACTIONTYPE)yyNewState; yytos->major = (YYCODETYPE)yyMajor; yytos->minor = *yypMinor; #ifndef NDEBUG if( yyTraceFILE && yypParser->yyidx>0 ){ int i; fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); for(i=1; i<=yypParser->yyidx; i++) fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); fprintf(yyTraceFILE,"\n"); } #endif } /* The following table contains information about every rule that ** is used during the reduce. */ static const struct { YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ unsigned char nrhs; /* Number of right-hand side symbols in the rule */ } yyRuleInfo[] = { %% }; static void yy_accept(yyParser*); /* Forward Declaration */ /* ** Perform a reduce action and the shift that must immediately ** follow the reduce. */ static void yy_reduce( yyParser *yypParser, /* The parser */ int yyruleno /* Number of the rule by which to reduce */ ){ int yygoto; /* The next state */ int yyact; /* The next action */ YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ ParseARG_FETCH; yymsp = &yypParser->yystack[yypParser->yyidx]; #ifndef NDEBUG if( yyTraceFILE && yyruleno>=0 && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, yyRuleName[yyruleno]); } #endif /* NDEBUG */ /* Silence complaints from purify about yygotominor being uninitialized ** in some cases when it is copied into the stack after the following ** switch. yygotominor is uninitialized when a rule reduces that does ** not set the value of its left-hand side nonterminal. Leaving the ** value of the nonterminal uninitialized is utterly harmless as long ** as the value is never used. So really the only thing this code ** accomplishes is to quieten purify. ** ** 2007-01-16: The wireshark project (www.wireshark.org) reports that ** without this code, their parser segfaults. I'm not sure what there ** parser is doing to make this happen. This is the second bug report ** from wireshark this week. Clearly they are stressing Lemon in ways ** that it has not been previously stressed... (SQLite ticket #2172) */ /*memset(&yygotominor, 0, sizeof(yygotominor));*/ yygotominor = yyzerominor; switch( yyruleno ){ /* Beginning here are the reduction cases. A typical example ** follows: ** case 0: ** #line ** { ... } // User supplied code ** #line ** break; */ %% }; yygoto = yyRuleInfo[yyruleno].lhs; yysize = yyRuleInfo[yyruleno].nrhs; yypParser->yyidx -= yysize; yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto); if( yyact < YYNSTATE ){ #ifdef NDEBUG /* If we are not debugging and the reduce action popped at least ** one element off the stack, then we can push the new element back ** onto the stack here, and skip the stack overflow test in yy_shift(). ** That gives a significant speed improvement. */ if( yysize ){ yypParser->yyidx++; yymsp -= yysize-1; yymsp->stateno = (YYACTIONTYPE)yyact; yymsp->major = (YYCODETYPE)yygoto; yymsp->minor = yygotominor; }else #endif { yy_shift(yypParser,yyact,yygoto,&yygotominor); } }else{ assert( yyact == YYNSTATE + YYNRULE + 1 ); yy_accept(yypParser); } } /* ** The following code executes when the parse fails */ #ifndef YYNOERRORRECOVERY static void yy_parse_failed( yyParser *yypParser /* The parser */ ){ ParseARG_FETCH; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); } #endif while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser fails */ %% ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } #endif /* YYNOERRORRECOVERY */ /* ** The following code executes when a syntax error first occurs. */ static void yy_syntax_error( yyParser *yypParser, /* The parser */ int yymajor, /* The major type of the error token */ YYMINORTYPE yyminor /* The minor type of the error token */ ){ ParseARG_FETCH; #define TOKEN (yyminor.yy0) %% ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* ** The following is executed when the parser accepts */ static void yy_accept( yyParser *yypParser /* The parser */ ){ ParseARG_FETCH; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); } #endif while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); /* Here code is inserted which will be executed whenever the ** parser accepts */ %% ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */ } /* The main parser program. ** The first argument is a pointer to a structure obtained from ** "ParseAlloc" which describes the current state of the parser. ** The second argument is the major token number. The third is ** the minor token. The fourth optional argument is whatever the ** user wants (and specified in the grammar) and is available for ** use by the action routines. ** ** Inputs: **
    **
  • A pointer to the parser (an opaque structure.) **
  • The major token number. **
  • The minor token number. **
  • An option argument of a grammar-specified type. **
** ** Outputs: ** None. */ void Parse( void *yyp, /* The parser */ int yymajor, /* The major token code number */ ParseTOKENTYPE yyminor /* The value for the token */ ParseARG_PDECL /* Optional %extra_argument parameter */ ){ YYMINORTYPE yyminorunion; int yyact; /* The parser action. */ int yyendofinput; /* True if we are at the end of input */ #ifdef YYERRORSYMBOL int yyerrorhit = 0; /* True if yymajor has invoked an error */ #endif yyParser *yypParser; /* The parser */ /* (re)initialize the parser, if necessary */ yypParser = (yyParser*)yyp; if( yypParser->yyidx<0 ){ #if YYSTACKDEPTH<=0 if( yypParser->yystksz <=0 ){ /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/ yyminorunion = yyzerominor; yyStackOverflow(yypParser, &yyminorunion); return; } #endif yypParser->yyidx = 0; yypParser->yyerrcnt = -1; yypParser->yystack[0].stateno = 0; yypParser->yystack[0].major = 0; } yyminorunion.yy0 = yyminor; yyendofinput = (yymajor==0); ParseARG_STORE; #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); } #endif do{ yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); if( yyactyyerrcnt--; yymajor = YYNOCODE; }else if( yyact < YYNSTATE + YYNRULE ){ yy_reduce(yypParser,yyact-YYNSTATE); }else{ assert( yyact == YY_ERROR_ACTION ); #ifdef YYERRORSYMBOL int yymx; #endif #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); } #endif #ifdef YYERRORSYMBOL /* A syntax error has occurred. ** The response to an error depends upon whether or not the ** grammar defines an error token "ERROR". ** ** This is what we do if the grammar does define ERROR: ** ** * Call the %syntax_error function. ** ** * Begin popping the stack until we enter a state where ** it is legal to shift the error symbol, then shift ** the error symbol. ** ** * Set the error count to three. ** ** * Begin accepting and shifting new tokens. No new error ** processing will occur until three tokens have been ** shifted successfully. ** */ if( yypParser->yyerrcnt<0 ){ yy_syntax_error(yypParser,yymajor,yyminorunion); } yymx = yypParser->yystack[yypParser->yyidx].major; if( yymx==YYERRORSYMBOL || yyerrorhit ){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE,"%sDiscard input token %s\n", yyTracePrompt,yyTokenName[yymajor]); } #endif yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion); yymajor = YYNOCODE; }else{ while( yypParser->yyidx >= 0 && yymx != YYERRORSYMBOL && (yyact = yy_find_reduce_action( yypParser->yystack[yypParser->yyidx].stateno, YYERRORSYMBOL)) >= YYNSTATE ){ yy_pop_parser_stack(yypParser); } if( yypParser->yyidx < 0 || yymajor==0 ){ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); yy_parse_failed(yypParser); yymajor = YYNOCODE; }else if( yymx!=YYERRORSYMBOL ){ YYMINORTYPE u2; u2.YYERRSYMDT = 0; yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); } } yypParser->yyerrcnt = 3; yyerrorhit = 1; #elif defined(YYNOERRORRECOVERY) /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to ** do any kind of error recovery. Instead, simply invoke the syntax ** error routine and continue going as if nothing had happened. ** ** Applications can set this macro (for example inside %include) if ** they intend to abandon the parse upon the first syntax error seen. */ yy_syntax_error(yypParser,yymajor,yyminorunion); yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); yymajor = YYNOCODE; #else /* YYERRORSYMBOL is not defined */ /* This is what we do if the grammar does not define ERROR: ** ** * Report an error message, and throw away the input token. ** ** * If the input token is $, then fail the parse. ** ** As before, subsequent error messages are suppressed until ** three input tokens have been successfully shifted. */ if( yypParser->yyerrcnt<=0 ){ yy_syntax_error(yypParser,yymajor,yyminorunion); } yypParser->yyerrcnt = 3; yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); if( yyendofinput ){ yy_parse_failed(yypParser); } yymajor = YYNOCODE; #endif } }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); return; } openvpn-auth-ldap-auth-ldap-2.0.4/tools/makeheaders.c000066400000000000000000003017611332642612100225210ustar00rootroot00000000000000static const char ident[] = "@(#) $Header: /cvstrac/cvstrac/makeheaders.c,v 1.4 2005/03/16 22:17:51 drh Exp $"; /* ** This program is free software; you can redistribute it and/or ** modify it under the terms of the Simplified BSD License (also ** known as the "2-Clause License" or "FreeBSD License".) ** ** Copyright 1993 D. Richard Hipp. All rights reserved. ** ** Redistribution and use in source and binary forms, with or ** without modification, are permitted provided that the following ** conditions are met: ** ** 1. Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** ** 2. Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** ** This software is provided "as is" and any express or implied warranties, ** including, but not limited to, the implied warranties of merchantability ** and fitness for a particular purpose are disclaimed. In no event shall ** the author or contributors be liable for any direct, indirect, incidental, ** special, exemplary, or consequential damages (including, but not limited ** to, procurement of substitute goods or services; loss of use, data or ** profits; or business interruption) however caused and on any theory of ** liability, whether in contract, strict liability, or tort (including ** negligence or otherwise) arising in any way out of the use of this ** software, even if advised of the possibility of such damage. ** ** 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. ** appropriate header files. */ #include #include #include #include #include #include #if defined( __MINGW32__) || defined(__DMC__) || defined(_MSC_VER) || defined(__POCC__) # ifndef WIN32 # define WIN32 # endif # include #else # include #endif /* ** Macros for debugging. */ #ifdef DEBUG static int debugMask = 0; # define debug0(F,M) if( (F)&debugMask ){ fprintf(stderr,M); } # define debug1(F,M,A) if( (F)&debugMask ){ fprintf(stderr,M,A); } # define debug2(F,M,A,B) if( (F)&debugMask ){ fprintf(stderr,M,A,B); } # define debug3(F,M,A,B,C) if( (F)&debugMask ){ fprintf(stderr,M,A,B,C); } # define PARSER 0x00000001 # define DECL_DUMP 0x00000002 # define TOKENIZER 0x00000004 #else # define debug0(Flags, Format) # define debug1(Flags, Format, A) # define debug2(Flags, Format, A, B) # define debug3(Flags, Format, A, B, C) #endif /* ** The following macros are purely for the purpose of testing this ** program on itself. They don't really contribute to the code. */ #define INTERFACE 1 #define EXPORT_INTERFACE 1 #define EXPORT /* ** Each token in a source file is represented by an instance of ** the following structure. Tokens are collected onto a list. */ typedef struct Token Token; struct Token { const char *zText; /* The text of the token */ int nText; /* Number of characters in the token's text */ int eType; /* The type of this token */ int nLine; /* The line number on which the token starts */ Token *pComment; /* Most recent block comment before this token */ Token *pNext; /* Next token on the list */ Token *pPrev; /* Previous token on the list */ }; /* ** During tokenization, information about the state of the input ** stream is held in an instance of the following structure */ typedef struct InStream InStream; struct InStream { const char *z; /* Complete text of the input */ int i; /* Next character to read from the input */ int nLine; /* The line number for character z[i] */ }; /* ** Each declaration in the C or C++ source files is parsed out and stored as ** an instance of the following structure. ** ** A "forward declaration" is a declaration that an object exists that ** doesn't tell about the objects structure. A typical forward declaration ** is: ** ** struct Xyzzy; ** ** Not every object has a forward declaration. If it does, thought, the ** forward declaration will be contained in the zFwd field for C and ** the zFwdCpp for C++. The zDecl field contains the complete ** declaration text. */ typedef struct Decl Decl; struct Decl { char *zName; /* Name of the object being declared. The appearance ** of this name is a source file triggers the declaration ** to be added to the header for that file. */ char *zFile; /* File from which extracted. */ char *zIf; /* Surround the declaration with this #if */ char *zFwd; /* A forward declaration. NULL if there is none. */ char *zFwdCpp; /* Use this forward declaration for C++. */ char *zDecl; /* A full declaration of this object */ char *zExtra; /* Extra declaration text inserted into class objects */ int extraType; /* Last public:, protected: or private: in zExtraDecl */ struct Include *pInclude; /* #includes that come before this declaration */ int flags; /* See the "Properties" below */ Token *pComment; /* A block comment associated with this declaration */ Token tokenCode; /* Implementation of functions and procedures */ Decl *pSameName; /* Next declaration with the same "zName" */ Decl *pSameHash; /* Next declaration with same hash but different zName */ Decl *pNext; /* Next declaration with a different name */ }; /* ** Properties associated with declarations. ** ** DP_Forward and DP_Declared are used during the generation of a single ** header file in order to prevent duplicate declarations and definitions. ** DP_Forward is set after the object has been given a forward declaration ** and DP_Declared is set after the object gets a full declarations. ** (Example: A forward declaration is "typedef struct Abc Abc;" and the ** full declaration is "struct Abc { int a; float b; };".) ** ** The DP_Export and DP_Local flags are more permanent. They mark objects ** that have EXPORT scope and LOCAL scope respectively. If both of these ** marks are missing, then the object has library scope. The meanings of ** the scopes are as follows: ** ** LOCAL scope The object is only usable within the file in ** which it is declared. ** ** library scope The object is visible and usable within other ** files in the same project. By if the project is ** a library, then the object is not visible to users ** of the library. (i.e. the object does not appear ** in the output when using the -H option.) ** ** EXPORT scope The object is visible and usable everywhere. ** ** The DP_Flag is a temporary use flag that is used during processing to ** prevent an infinite loop. It's use is localized. ** ** The DP_Cplusplus, DP_ExternCReqd and DP_ExternReqd flags are permanent ** and are used to specify what type of declaration the object requires. */ #define DP_Forward 0x001 /* Has a forward declaration in this file */ #define DP_Declared 0x002 /* Has a full declaration in this file */ #define DP_Export 0x004 /* Export this declaration */ #define DP_Local 0x008 /* Declare in its home file only */ #define DP_Flag 0x010 /* Use to mark a subset of a Decl list ** for special processing */ #define DP_Cplusplus 0x020 /* Has C++ linkage and cannot appear in a ** C header file */ #define DP_ExternCReqd 0x040 /* Prepend 'extern "C"' in a C++ header. ** Prepend nothing in a C header */ #define DP_ExternReqd 0x080 /* Prepend 'extern "C"' in a C++ header if ** DP_Cplusplus is not also set. If DP_Cplusplus ** is set or this is a C header then ** prepend 'extern' */ /* ** Convenience macros for dealing with declaration properties */ #define DeclHasProperty(D,P) (((D)->flags&(P))==(P)) #define DeclHasAnyProperty(D,P) (((D)->flags&(P))!=0) #define DeclSetProperty(D,P) (D)->flags |= (P) #define DeclClearProperty(D,P) (D)->flags &= ~(P) /* ** These are state properties of the parser. Each of the values is ** distinct from the DP_ values above so that both can be used in ** the same "flags" field. ** ** Be careful not to confuse PS_Export with DP_Export or ** PS_Local with DP_Local. Their names are similar, but the meanings ** of these flags are very different. */ #define PS_Extern 0x000800 /* "extern" has been seen */ #define PS_Export 0x001000 /* If between "#if EXPORT_INTERFACE" ** and "#endif" */ #define PS_Export2 0x002000 /* If "EXPORT" seen */ #define PS_Typedef 0x004000 /* If "typedef" has been seen */ #define PS_Static 0x008000 /* If "static" has been seen */ #define PS_Interface 0x010000 /* If within #if INTERFACE..#endif */ #define PS_Method 0x020000 /* If "::" token has been seen */ #define PS_Local 0x040000 /* If within #if LOCAL_INTERFACE..#endif */ #define PS_Local2 0x080000 /* If "LOCAL" seen. */ #define PS_Public 0x100000 /* If "PUBLIC" seen. */ #define PS_Protected 0x200000 /* If "PROTECTED" seen. */ #define PS_Private 0x400000 /* If "PRIVATE" seen. */ #define PS_PPP 0x700000 /* If any of PUBLIC, PRIVATE, PROTECTED */ /* ** The following set of flags are ORed into the "flags" field of ** a Decl in order to identify what type of object is being ** declared. */ #define TY_Class 0x00100000 #define TY_Subroutine 0x00200000 #define TY_Macro 0x00400000 #define TY_Typedef 0x00800000 #define TY_Variable 0x01000000 #define TY_Structure 0x02000000 #define TY_Union 0x04000000 #define TY_Enumeration 0x08000000 #define TY_Defunct 0x10000000 /* Used to erase a declaration */ /* ** Each nested #if (or #ifdef or #ifndef) is stored in a stack of ** instances of the following structure. */ typedef struct Ifmacro Ifmacro; struct Ifmacro { int nLine; /* Line number where this macro occurs */ char *zCondition; /* Text of the condition for this macro */ Ifmacro *pNext; /* Next down in the stack */ int flags; /* Can hold PS_Export, PS_Interface or PS_Local flags */ }; /* ** When parsing a file, we need to keep track of what other files have ** be #include-ed. For each #include found, we create an instance of ** the following structure. */ typedef struct Include Include; struct Include { char *zFile; /* The name of file include. Includes "" or <> */ char *zIf; /* If not NULL, #include should be enclosed in #if */ char *zLabel; /* A unique label used to test if this #include has * appeared already in a file or not */ Include *pNext; /* Previous include file, or NULL if this is the first */ }; /* ** Identifiers found in a source file that might be used later to provoke ** the copying of a declaration into the corresponding header file are ** stored in a hash table as instances of the following structure. */ typedef struct Ident Ident; struct Ident { char *zName; /* The text of this identifier */ Ident *pCollide; /* Next identifier with the same hash */ Ident *pNext; /* Next identifier in a list of them all */ }; /* ** A complete table of identifiers is stored in an instance of ** the next structure. */ #define IDENT_HASH_SIZE 2237 typedef struct IdentTable IdentTable; struct IdentTable { Ident *pList; /* List of all identifiers in this table */ Ident *apTable[IDENT_HASH_SIZE]; /* The hash table */ }; /* ** The following structure holds all information for a single ** source file named on the command line of this program. */ typedef struct InFile InFile; struct InFile { char *zSrc; /* Name of input file */ char *zHdr; /* Name of the generated .h file for this input. ** Will be NULL if input is to be scanned only */ int flags; /* One or more DP_, PS_ and/or TY_ flags */ InFile *pNext; /* Next input file in the list of them all */ IdentTable idTable; /* All identifiers in this input file */ }; /* ** An unbounded string is able to grow without limit. We use these ** to construct large in-memory strings from lots of smaller components. */ typedef struct String String; struct String { int nAlloc; /* Number of bytes allocated */ int nUsed; /* Number of bytes used (not counting null terminator) */ char *zText; /* Text of the string */ }; /* ** The following structure contains a lot of state information used ** while generating a .h file. We put the information in this structure ** and pass around a pointer to this structure, rather than pass around ** all of the information separately. This helps reduce the number of ** arguments to generator functions. */ typedef struct GenState GenState; struct GenState { String *pStr; /* Write output to this string */ IdentTable *pTable; /* A table holding the zLabel of every #include that * has already been generated. Used to avoid * generating duplicate #includes. */ const char *zIf; /* If not NULL, then we are within a #if with * this argument. */ int nErr; /* Number of errors */ const char *zFilename; /* Name of the source file being scanned */ int flags; /* Various flags (DP_ and PS_ flags above) */ }; /* ** The following text line appears at the top of every file generated ** by this program. By recognizing this line, the program can be sure ** never to read a file that it generated itself. */ const char zTopLine[] = "/* \aThis file was automatically generated. Do not edit! */\n"; #define nTopLine (sizeof(zTopLine)-1) /* ** The name of the file currently being parsed. */ static char *zFilename; /* ** The stack of #if macros for the file currently being parsed. */ static Ifmacro *ifStack = 0; /* ** A list of all files that have been #included so far in a file being ** parsed. */ static Include *includeList = 0; /* ** The last block comment seen. */ static Token *blockComment = 0; /* ** The following flag is set if the -doc flag appears on the ** command line. */ static int doc_flag = 0; /* ** If the following flag is set, then makeheaders will attempt to ** generate prototypes for static functions and procedures. */ static int proto_static = 0; /* ** A list of all declarations. The list is held together using the ** pNext field of the Decl structure. */ static Decl *pDeclFirst; /* First on the list */ static Decl *pDeclLast; /* Last on the list */ /* ** A hash table of all declarations */ #define DECL_HASH_SIZE 3371 static Decl *apTable[DECL_HASH_SIZE]; /* ** The TEST macro must be defined to something. Make sure this is the ** case. */ #ifndef TEST # define TEST 0 #endif #ifdef NOT_USED /* ** We do our own assertion macro so that we can have more control ** over debugging. */ #define Assert(X) if(!(X)){ CantHappen(__LINE__); } #define CANT_HAPPEN CantHappen(__LINE__) static void CantHappen(int iLine){ fprintf(stderr,"Assertion failed on line %d\n",iLine); *(char*)1 = 0; /* Force a core-dump */ } #endif /* ** Memory allocation functions that are guaranteed never to return NULL. */ static void *SafeMalloc(int nByte){ void *p = malloc( nByte ); if( p==0 ){ fprintf(stderr,"Out of memory. Can't allocate %d bytes.\n",nByte); exit(1); } return p; } static void SafeFree(void *pOld){ if( pOld ){ free(pOld); } } static void *SafeRealloc(void *pOld, int nByte){ void *p; if( pOld==0 ){ p = SafeMalloc(nByte); }else{ p = realloc(pOld, nByte); if( p==0 ){ fprintf(stderr, "Out of memory. Can't enlarge an allocation to %d bytes\n",nByte); exit(1); } } return p; } static char *StrDup(const char *zSrc, int nByte){ char *zDest; if( nByte<=0 ){ nByte = strlen(zSrc); } zDest = SafeMalloc( nByte + 1 ); strncpy(zDest,zSrc,nByte); zDest[nByte] = 0; return zDest; } /* ** Return TRUE if the character X can be part of an identifier */ #define ISALNUM(X) ((X)=='_' || isalnum(X)) /* ** Routines for dealing with unbounded strings. */ static void StringInit(String *pStr){ pStr->nAlloc = 0; pStr->nUsed = 0; pStr->zText = 0; } static void StringReset(String *pStr){ SafeFree(pStr->zText); StringInit(pStr); } static void StringAppend(String *pStr, const char *zText, int nByte){ if( nByte<=0 ){ nByte = strlen(zText); } if( pStr->nUsed + nByte >= pStr->nAlloc ){ if( pStr->nAlloc==0 ){ pStr->nAlloc = nByte + 100; pStr->zText = SafeMalloc( pStr->nAlloc ); }else{ pStr->nAlloc = pStr->nAlloc*2 + nByte; pStr->zText = SafeRealloc(pStr->zText, pStr->nAlloc); } } strncpy(&pStr->zText[pStr->nUsed],zText,nByte); pStr->nUsed += nByte; pStr->zText[pStr->nUsed] = 0; } #define StringGet(S) ((S)->zText?(S)->zText:"") /* ** Compute a hash on a string. The number returned is a non-negative ** value between 0 and 2**31 - 1 */ static int Hash(const char *z, int n){ int h = 0; if( n<=0 ){ n = strlen(z); } while( n-- ){ h = h ^ (h<<5) ^ *z++; } return h & 0x7fffffff; } /* ** Given an identifier name, try to find a declaration for that ** identifier in the hash table. If found, return a pointer to ** the Decl structure. If not found, return 0. */ static Decl *FindDecl(const char *zName, int len){ int h; Decl *p; if( len<=0 ){ len = strlen(zName); } h = Hash(zName,len) % DECL_HASH_SIZE; p = apTable[h]; while( p && (strncmp(p->zName,zName,len)!=0 || p->zName[len]!=0) ){ p = p->pSameHash; } return p; } /* ** Install the given declaration both in the hash table and on ** the list of all declarations. */ static void InstallDecl(Decl *pDecl){ int h; Decl *pOther; h = Hash(pDecl->zName,0) % DECL_HASH_SIZE; pOther = apTable[h]; while( pOther && strcmp(pDecl->zName,pOther->zName)!=0 ){ pOther = pOther->pSameHash; } if( pOther ){ pDecl->pSameName = pOther->pSameName; pOther->pSameName = pDecl; }else{ pDecl->pSameName = 0; pDecl->pSameHash = apTable[h]; apTable[h] = pDecl; } pDecl->pNext = 0; if( pDeclFirst==0 ){ pDeclFirst = pDeclLast = pDecl; }else{ pDeclLast->pNext = pDecl; pDeclLast = pDecl; } } /* ** Look at the current ifStack. If anything declared at the current ** position must be surrounded with ** ** #if STUFF ** #endif ** ** Then this routine computes STUFF and returns a pointer to it. Memory ** to hold the value returned is obtained from malloc(). */ static char *GetIfString(void){ Ifmacro *pIf; char *zResult = 0; int hasIf = 0; String str; for(pIf = ifStack; pIf; pIf=pIf->pNext){ if( pIf->zCondition==0 || *pIf->zCondition==0 ) continue; if( !hasIf ){ hasIf = 1; StringInit(&str); }else{ StringAppend(&str," && ",4); } StringAppend(&str,pIf->zCondition,0); } if( hasIf ){ zResult = StrDup(StringGet(&str),0); StringReset(&str); }else{ zResult = 0; } return zResult; } /* ** Create a new declaration and put it in the hash table. Also ** return a pointer to it so that we can fill in the zFwd and zDecl ** fields, and so forth. */ static Decl *CreateDecl( const char *zName, /* Name of the object being declared. */ int nName /* Length of the name */ ){ Decl *pDecl; pDecl = SafeMalloc( sizeof(Decl) + nName + 1); memset(pDecl,0,sizeof(Decl)); pDecl->zName = (char*)&pDecl[1]; sprintf(pDecl->zName,"%.*s",nName,zName); pDecl->zFile = zFilename; pDecl->pInclude = includeList; pDecl->zIf = GetIfString(); InstallDecl(pDecl); return pDecl; } /* ** Insert a new identifier into an table of identifiers. Return TRUE if ** a new identifier was inserted and return FALSE if the identifier was ** already in the table. */ static int IdentTableInsert( IdentTable *pTable, /* The table into which we will insert */ const char *zId, /* Name of the identifiers */ int nId /* Length of the identifier name */ ){ int h; Ident *pId; if( nId<=0 ){ nId = strlen(zId); } h = Hash(zId,nId) % IDENT_HASH_SIZE; for(pId = pTable->apTable[h]; pId; pId=pId->pCollide){ if( strncmp(zId,pId->zName,nId)==0 && pId->zName[nId]==0 ){ /* printf("Already in table: %.*s\n",nId,zId); */ return 0; } } pId = SafeMalloc( sizeof(Ident) + nId + 1 ); pId->zName = (char*)&pId[1]; sprintf(pId->zName,"%.*s",nId,zId); pId->pNext = pTable->pList; pTable->pList = pId; pId->pCollide = pTable->apTable[h]; pTable->apTable[h] = pId; /* printf("Add to table: %.*s\n",nId,zId); */ return 1; } /* ** Check to see if the given value is in the given IdentTable. Return ** true if it is and false if it is not. */ static int IdentTableTest( IdentTable *pTable, /* The table in which to search */ const char *zId, /* Name of the identifiers */ int nId /* Length of the identifier name */ ){ int h; Ident *pId; if( nId<=0 ){ nId = strlen(zId); } h = Hash(zId,nId) % IDENT_HASH_SIZE; for(pId = pTable->apTable[h]; pId; pId=pId->pCollide){ if( strncmp(zId,pId->zName,nId)==0 && pId->zName[nId]==0 ){ return 1; } } return 0; } /* ** Remove every identifier from the given table. Reset the table to ** its initial state. */ static void IdentTableReset(IdentTable *pTable){ Ident *pId, *pNext; for(pId = pTable->pList; pId; pId = pNext){ pNext = pId->pNext; SafeFree(pId); } memset(pTable,0,sizeof(IdentTable)); } #ifdef DEBUG /* ** Print the name of every identifier in the given table, one per line */ static void IdentTablePrint(IdentTable *pTable, FILE *pOut){ Ident *pId; for(pId = pTable->pList; pId; pId = pId->pNext){ fprintf(pOut,"%s\n",pId->zName); } } #endif /* ** Read an entire file into memory. Return a pointer to the memory. ** ** The memory is obtained from SafeMalloc and must be freed by the ** calling function. ** ** If the read fails for any reason, 0 is returned. */ static char *ReadFile(const char *zFilename){ struct stat sStat; FILE *pIn; char *zBuf; int n; if( stat(zFilename,&sStat)!=0 #ifndef WIN32 || !S_ISREG(sStat.st_mode) #endif ){ return 0; } pIn = fopen(zFilename,"r"); if( pIn==0 ){ return 0; } zBuf = SafeMalloc( sStat.st_size + 1 ); n = fread(zBuf,1,sStat.st_size,pIn); zBuf[n] = 0; fclose(pIn); return zBuf; } /* ** Write the contents of a string into a file. Return the number of ** errors */ static int WriteFile(const char *zFilename, const char *zOutput){ FILE *pOut; pOut = fopen(zFilename,"w"); if( pOut==0 ){ return 1; } fwrite(zOutput,1,strlen(zOutput),pOut); fclose(pOut); return 0; } /* ** Major token types */ #define TT_Space 1 /* Contiguous white space */ #define TT_Id 2 /* An identifier */ #define TT_Preprocessor 3 /* Any C preprocessor directive */ #define TT_Comment 4 /* Either C or C++ style comment */ #define TT_Number 5 /* Any numeric constant */ #define TT_String 6 /* String or character constants. ".." or '.' */ #define TT_Braces 7 /* All text between { and a matching } */ #define TT_EOF 8 /* End of file */ #define TT_Error 9 /* An error condition */ #define TT_BlockComment 10 /* A C-Style comment at the left margin that * spans multple lines */ #define TT_Other 0 /* None of the above */ /* ** Get a single low-level token from the input file. Update the ** file pointer so that it points to the first character beyond the ** token. ** ** A "low-level token" is any token except TT_Braces. A TT_Braces token ** consists of many smaller tokens and is assembled by a routine that ** calls this one. ** ** The function returns the number of errors. An error is an ** unterminated string or character literal or an unterminated ** comment. ** ** Profiling shows that this routine consumes about half the ** CPU time on a typical run of makeheaders. */ static int GetToken(InStream *pIn, Token *pToken){ int i; const char *z; int cStart; int c; int startLine; /* Line on which a structure begins */ int nlisc = 0; /* True if there is a new-line in a ".." or '..' */ int nErr = 0; /* Number of errors seen */ z = pIn->z; i = pIn->i; pToken->nLine = pIn->nLine; pToken->zText = &z[i]; switch( z[i] ){ case 0: pToken->eType = TT_EOF; pToken->nText = 0; break; case '#': if( i==0 || z[i-1]=='\n' || (i>1 && z[i-1]=='\r' && z[i-2]=='\n')){ /* We found a preprocessor statement */ pToken->eType = TT_Preprocessor; i++; while( z[i]!=0 && z[i]!='\n' ){ if( z[i]=='\\' ){ i++; if( z[i]=='\n' ) pIn->nLine++; } i++; } pToken->nText = i - pIn->i; }else{ /* Just an operator */ pToken->eType = TT_Other; pToken->nText = 1; } break; case ' ': case '\t': case '\r': case '\f': case '\n': while( isspace(z[i]) ){ if( z[i]=='\n' ) pIn->nLine++; i++; } pToken->eType = TT_Space; pToken->nText = i - pIn->i; break; case '\\': pToken->nText = 2; pToken->eType = TT_Other; if( z[i+1]=='\n' ){ pIn->nLine++; pToken->eType = TT_Space; }else if( z[i+1]==0 ){ pToken->nText = 1; } break; case '\'': case '\"': cStart = z[i]; startLine = pIn->nLine; do{ i++; c = z[i]; if( c=='\n' ){ if( !nlisc ){ fprintf(stderr, "%s:%d: (warning) Newline in string or character literal.\n", zFilename, pIn->nLine); nlisc = 1; } pIn->nLine++; } if( c=='\\' ){ i++; c = z[i]; if( c=='\n' ){ pIn->nLine++; } }else if( c==cStart ){ i++; c = 0; }else if( c==0 ){ fprintf(stderr, "%s:%d: Unterminated string or character literal.\n", zFilename, startLine); nErr++; } }while( c ); pToken->eType = TT_String; pToken->nText = i - pIn->i; break; case '/': if( z[i+1]=='/' ){ /* C++ style comment */ while( z[i] && z[i]!='\n' ){ i++; } pToken->eType = TT_Comment; pToken->nText = i - pIn->i; }else if( z[i+1]=='*' ){ /* C style comment */ int isBlockComment = i==0 || z[i-1]=='\n'; i += 2; startLine = pIn->nLine; while( z[i] && (z[i]!='*' || z[i+1]!='/') ){ if( z[i]=='\n' ){ pIn->nLine++; if( isBlockComment ){ if( z[i+1]=='*' || z[i+2]=='*' ){ isBlockComment = 2; }else{ isBlockComment = 0; } } } i++; } if( z[i] ){ i += 2; }else{ isBlockComment = 0; fprintf(stderr,"%s:%d: Unterminated comment\n", zFilename, startLine); nErr++; } pToken->eType = isBlockComment==2 ? TT_BlockComment : TT_Comment; pToken->nText = i - pIn->i; }else{ /* A divide operator */ pToken->eType = TT_Other; pToken->nText = 1 + (z[i+1]=='+'); } break; case '0': if( z[i+1]=='x' || z[i+1]=='X' ){ /* A hex constant */ i += 2; while( isxdigit(z[i]) ){ i++; } }else{ /* An octal constant */ while( isdigit(z[i]) ){ i++; } } pToken->eType = TT_Number; pToken->nText = i - pIn->i; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': while( isdigit(z[i]) ){ i++; } if( (c=z[i])=='.' ){ i++; while( isdigit(z[i]) ){ i++; } c = z[i]; if( c=='e' || c=='E' ){ i++; if( ((c=z[i])=='+' || c=='-') && isdigit(z[i+1]) ){ i++; } while( isdigit(z[i]) ){ i++; } c = z[i]; } if( c=='f' || c=='F' || c=='l' || c=='L' ){ i++; } }else if( c=='e' || c=='E' ){ i++; if( ((c=z[i])=='+' || c=='-') && isdigit(z[i+1]) ){ i++; } while( isdigit(z[i]) ){ i++; } }else if( c=='L' || c=='l' ){ i++; c = z[i]; if( c=='u' || c=='U' ){ i++; } }else if( c=='u' || c=='U' ){ i++; c = z[i]; if( c=='l' || c=='L' ){ i++; } } pToken->eType = TT_Number; pToken->nText = i - pIn->i; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': while( isalnum(z[i]) || z[i]=='_' ){ i++; }; pToken->eType = TT_Id; pToken->nText = i - pIn->i; break; case ':': pToken->eType = TT_Other; pToken->nText = 1 + (z[i+1]==':'); break; case '=': case '<': case '>': case '+': case '-': case '*': case '%': case '^': case '&': case '|': pToken->eType = TT_Other; pToken->nText = 1 + (z[i+1]=='='); break; default: pToken->eType = TT_Other; pToken->nText = 1; break; } pIn->i += pToken->nText; return nErr; } /* ** This routine recovers the next token from the input file which is ** not a space or a comment or any text between an "#if 0" and "#endif". ** ** This routine returns the number of errors encountered. An error ** is an unterminated token or unmatched "#if 0". ** ** Profiling shows that this routine uses about a quarter of the ** CPU time in a typical run. */ static int GetNonspaceToken(InStream *pIn, Token *pToken){ int nIf = 0; int inZero = 0; const char *z; int value; int startLine; int nErr = 0; startLine = pIn->nLine; while( 1 ){ nErr += GetToken(pIn,pToken); /* printf("%04d: Type=%d nIf=%d [%.*s]\n", pToken->nLine,pToken->eType,nIf,pToken->nText, pToken->eType!=TT_Space ? pToken->zText : ""); */ pToken->pComment = blockComment; switch( pToken->eType ){ case TT_Comment: case TT_Space: break; case TT_BlockComment: if( doc_flag ){ blockComment = SafeMalloc( sizeof(Token) ); *blockComment = *pToken; } break; case TT_EOF: if( nIf ){ fprintf(stderr,"%s:%d: Unterminated \"#if\"\n", zFilename, startLine); nErr++; } return nErr; case TT_Preprocessor: z = &pToken->zText[1]; while( *z==' ' || *z=='\t' ) z++; if( sscanf(z,"if %d",&value)==1 && value==0 ){ nIf++; inZero = 1; }else if( inZero ){ if( strncmp(z,"if",2)==0 ){ nIf++; }else if( strncmp(z,"endif",5)==0 ){ nIf--; if( nIf==0 ) inZero = 0; } }else{ return nErr; } break; default: if( !inZero ){ return nErr; } break; } } /* NOT REACHED */ } /* ** This routine looks for identifiers (strings of contiguous alphanumeric ** characters) within a preprocessor directive and adds every such string ** found to the given identifier table */ static void FindIdentifiersInMacro(Token *pToken, IdentTable *pTable){ Token sToken; InStream sIn; int go = 1; sIn.z = pToken->zText; sIn.i = 1; sIn.nLine = 1; while( go && sIn.i < pToken->nText ){ GetToken(&sIn,&sToken); switch( sToken.eType ){ case TT_Id: IdentTableInsert(pTable,sToken.zText,sToken.nText); break; case TT_EOF: go = 0; break; default: break; } } } /* ** This routine gets the next token. Everything contained within ** {...} is collapsed into a single TT_Braces token. Whitespace is ** omitted. ** ** If pTable is not NULL, then insert every identifier seen into the ** IdentTable. This includes any identifiers seen inside of {...}. ** ** The number of errors encountered is returned. An error is an ** unterminated token. */ static int GetBigToken(InStream *pIn, Token *pToken, IdentTable *pTable){ const char *z, *zStart; int iStart; int nBrace; int c; int nLine; int nErr; nErr = GetNonspaceToken(pIn,pToken); switch( pToken->eType ){ case TT_Id: if( pTable!=0 ){ IdentTableInsert(pTable,pToken->zText,pToken->nText); } return nErr; case TT_Preprocessor: if( pTable!=0 ){ FindIdentifiersInMacro(pToken,pTable); } return nErr; case TT_Other: if( pToken->zText[0]=='{' ) break; return nErr; default: return nErr; } z = pIn->z; iStart = pIn->i; zStart = pToken->zText; nLine = pToken->nLine; nBrace = 1; while( nBrace ){ nErr += GetNonspaceToken(pIn,pToken); /* printf("%04d: nBrace=%d [%.*s]\n",pToken->nLine,nBrace, pToken->nText,pToken->zText); */ switch( pToken->eType ){ case TT_EOF: fprintf(stderr,"%s:%d: Unterminated \"{\"\n", zFilename, nLine); nErr++; pToken->eType = TT_Error; return nErr; case TT_Id: if( pTable ){ IdentTableInsert(pTable,pToken->zText,pToken->nText); } break; case TT_Preprocessor: if( pTable!=0 ){ FindIdentifiersInMacro(pToken,pTable); } break; case TT_Other: if( (c = pToken->zText[0])=='{' ){ nBrace++; }else if( c=='}' ){ nBrace--; } break; default: break; } } pToken->eType = TT_Braces; pToken->nText = 1 + pIn->i - iStart; pToken->zText = zStart; pToken->nLine = nLine; return nErr; } /* ** This routine frees up a list of Tokens. The pComment tokens are ** not cleared by this. So we leak a little memory when using the -doc ** option. So what. */ static void FreeTokenList(Token *pList){ Token *pNext; while( pList ){ pNext = pList->pNext; SafeFree(pList); pList = pNext; } } /* ** Tokenize an entire file. Return a pointer to the list of tokens. ** ** Space for each token is obtained from a separate malloc() call. The ** calling function is responsible for freeing this space. ** ** If pTable is not NULL, then fill the table with all identifiers seen in ** the input file. */ static Token *TokenizeFile(const char *zFile, IdentTable *pTable){ InStream sIn; Token *pFirst = 0, *pLast = 0, *pNew; int nErr = 0; sIn.z = zFile; sIn.i = 0; sIn.nLine = 1; blockComment = 0; while( sIn.z[sIn.i]!=0 ){ pNew = SafeMalloc( sizeof(Token) ); nErr += GetBigToken(&sIn,pNew,pTable); debug3(TOKENIZER, "Token on line %d: [%.*s]\n", pNew->nLine, pNew->nText<50 ? pNew->nText : 50, pNew->zText); if( pFirst==0 ){ pFirst = pLast = pNew; pNew->pPrev = 0; }else{ pLast->pNext = pNew; pNew->pPrev = pLast; pLast = pNew; } if( pNew->eType==TT_EOF ) break; } if( pLast ) pLast->pNext = 0; blockComment = 0; if( nErr ){ FreeTokenList(pFirst); pFirst = 0; } return pFirst; } #if TEST==1 /* ** Use the following routine to test or debug the tokenizer. */ void main(int argc, char **argv){ char *zFile; Token *pList, *p; IdentTable sTable; if( argc!=2 ){ fprintf(stderr,"Usage: %s filename\n",*argv); exit(1); } memset(&sTable,0,sizeof(sTable)); zFile = ReadFile(argv[1]); if( zFile==0 ){ fprintf(stderr,"Can't read file \"%s\"\n",argv[1]); exit(1); } pList = TokenizeFile(zFile,&sTable); for(p=pList; p; p=p->pNext){ int j; switch( p->eType ){ case TT_Space: printf("%4d: Space\n",p->nLine); break; case TT_Id: printf("%4d: Id %.*s\n",p->nLine,p->nText,p->zText); break; case TT_Preprocessor: printf("%4d: Preprocessor %.*s\n",p->nLine,p->nText,p->zText); break; case TT_Comment: printf("%4d: Comment\n",p->nLine); break; case TT_BlockComment: printf("%4d: Block Comment\n",p->nLine); break; case TT_Number: printf("%4d: Number %.*s\n",p->nLine,p->nText,p->zText); break; case TT_String: printf("%4d: String %.*s\n",p->nLine,p->nText,p->zText); break; case TT_Other: printf("%4d: Other %.*s\n",p->nLine,p->nText,p->zText); break; case TT_Braces: for(j=0; jnText && j<30 && p->zText[j]!='\n'; j++){} printf("%4d: Braces %.*s...}\n",p->nLine,j,p->zText); break; case TT_EOF: printf("%4d: End of file\n",p->nLine); break; default: printf("%4d: type %d\n",p->nLine,p->eType); break; } } FreeTokenList(pList); SafeFree(zFile); IdentTablePrint(&sTable,stdout); } #endif #ifdef DEBUG /* ** For debugging purposes, write out a list of tokens. */ static void PrintTokens(Token *pFirst, Token *pLast){ int needSpace = 0; int c; pLast = pLast->pNext; while( pFirst!=pLast ){ switch( pFirst->eType ){ case TT_Preprocessor: printf("\n%.*s\n",pFirst->nText,pFirst->zText); needSpace = 0; break; case TT_Id: case TT_Number: printf("%s%.*s", needSpace ? " " : "", pFirst->nText, pFirst->zText); needSpace = 1; break; default: c = pFirst->zText[0]; printf("%s%.*s", (needSpace && (c=='*' || c=='{')) ? " " : "", pFirst->nText, pFirst->zText); needSpace = pFirst->zText[0]==','; break; } pFirst = pFirst->pNext; } } #endif /* ** Convert a sequence of tokens into a string and return a pointer ** to that string. Space to hold the string is obtained from malloc() ** and must be freed by the calling function. ** ** Certain keywords (EXPORT, PRIVATE, PUBLIC, PROTECTED) are always ** skipped. ** ** If pSkip!=0 then skip over nSkip tokens beginning with pSkip. ** ** If zTerm!=0 then append the text to the end. */ static char *TokensToString( Token *pFirst, /* First token in the string */ Token *pLast, /* Last token in the string */ char *zTerm, /* Terminate the string with this text if not NULL */ Token *pSkip, /* Skip this token if not NULL */ int nSkip /* Skip a total of this many tokens */ ){ char *zReturn; String str; int needSpace = 0; int c; int iSkip = 0; int skipOne = 0; StringInit(&str); pLast = pLast->pNext; while( pFirst!=pLast ){ if( pFirst==pSkip ){ iSkip = nSkip; } if( iSkip>0 ){ iSkip--; pFirst=pFirst->pNext; continue; } switch( pFirst->eType ){ case TT_Preprocessor: StringAppend(&str,"\n",1); StringAppend(&str,pFirst->zText,pFirst->nText); StringAppend(&str,"\n",1); needSpace = 0; break; case TT_Id: switch( pFirst->zText[0] ){ case 'E': if( pFirst->nText==6 && strncmp(pFirst->zText,"EXPORT",6)==0 ){ skipOne = 1; } break; case 'P': switch( pFirst->nText ){ case 6: skipOne = !strncmp(pFirst->zText,"PUBLIC", 6); break; case 7: skipOne = !strncmp(pFirst->zText,"PRIVATE",7); break; case 9: skipOne = !strncmp(pFirst->zText,"PROTECTED",9); break; default: break; } break; default: break; } if( skipOne ){ pFirst = pFirst->pNext; continue; } /* Fall thru to the next case */ case TT_Number: if( needSpace ){ StringAppend(&str," ",1); } StringAppend(&str,pFirst->zText,pFirst->nText); needSpace = 1; break; default: c = pFirst->zText[0]; if( needSpace && (c=='*' || c=='{') ){ StringAppend(&str," ",1); } StringAppend(&str,pFirst->zText,pFirst->nText); /* needSpace = pFirst->zText[0]==','; */ needSpace = 0; break; } pFirst = pFirst->pNext; } if( zTerm && *zTerm ){ StringAppend(&str,zTerm,strlen(zTerm)); } zReturn = StrDup(StringGet(&str),0); StringReset(&str); return zReturn; } /* ** This routine is called when we see one of the keywords "struct", ** "enum", "union" or "class". This might be the beginning of a ** type declaration. This routine will process the declaration and ** remove the declaration tokens from the input stream. ** ** If this is a type declaration that is immediately followed by a ** semicolon (in other words it isn't also a variable definition) ** then set *pReset to ';'. Otherwise leave *pReset at 0. The ** *pReset flag causes the parser to skip ahead to the next token ** that begins with the value placed in the *pReset flag, if that ** value is different from 0. */ static int ProcessTypeDecl(Token *pList, int flags, int *pReset){ Token *pName, *pEnd; Decl *pDecl; String str; int need_to_collapse = 1; int type = 0; *pReset = 0; if( pList==0 || pList->pNext==0 || pList->pNext->eType!=TT_Id ){ return 0; } pName = pList->pNext; /* Catch the case of "struct Foo;" and skip it. */ if( pName->pNext && pName->pNext->zText[0]==';' ){ *pReset = ';'; return 0; } for(pEnd=pName->pNext; pEnd && pEnd->eType!=TT_Braces; pEnd=pEnd->pNext){ switch( pEnd->zText[0] ){ case '(': case '*': case '[': case '=': case ';': return 0; } } if( pEnd==0 ){ return 0; } /* ** At this point, we know we have a type declaration that is bounded ** by pList and pEnd and has the name pName. */ /* ** If the braces are followed immedately by a semicolon, then we are ** dealing a type declaration only. There is not variable definition ** following the type declaration. So reset... */ if( pEnd->pNext==0 || pEnd->pNext->zText[0]==';' ){ *pReset = ';'; need_to_collapse = 0; }else{ need_to_collapse = 1; } if( proto_static==0 && (flags & (PS_Local|PS_Export|PS_Interface))==0 ){ /* Ignore these objects unless they are explicitly declared as interface, ** or unless the "-local" command line option was specified. */ *pReset = ';'; return 0; } #ifdef DEBUG if( debugMask & PARSER ){ printf("**** Found type: %.*s %.*s...\n", pList->nText, pList->zText, pName->nText, pName->zText); PrintTokens(pList,pEnd); printf(";\n"); } #endif /* ** Create a new Decl object for this definition. Actually, if this ** is a C++ class definition, then the Decl object might already exist, ** so check first for that case before creating a new one. */ switch( *pList->zText ){ case 'c': type = TY_Class; break; case 's': type = TY_Structure; break; case 'e': type = TY_Enumeration; break; case 'u': type = TY_Union; break; default: /* Can't Happen */ break; } if( type!=TY_Class ){ pDecl = 0; }else{ pDecl = FindDecl(pName->zText, pName->nText); if( pDecl && (pDecl->flags & type)!=type ) pDecl = 0; } if( pDecl==0 ){ pDecl = CreateDecl(pName->zText,pName->nText); } if( (flags & PS_Static) || !(flags & (PS_Interface|PS_Export)) ){ DeclSetProperty(pDecl,DP_Local); } DeclSetProperty(pDecl,type); /* The object has a full declaration only if it is contained within ** "#if INTERFACE...#endif" or "#if EXPORT_INTERFACE...#endif" or ** "#if LOCAL_INTERFACE...#endif". Otherwise, we only give it a ** forward declaration. */ if( flags & (PS_Local | PS_Export | PS_Interface) ){ pDecl->zDecl = TokensToString(pList,pEnd,";\n",0,0); }else{ pDecl->zDecl = 0; } pDecl->pComment = pList->pComment; StringInit(&str); StringAppend(&str,"typedef ",0); StringAppend(&str,pList->zText,pList->nText); StringAppend(&str," ",0); StringAppend(&str,pName->zText,pName->nText); StringAppend(&str," ",0); StringAppend(&str,pName->zText,pName->nText); StringAppend(&str,";\n",2); pDecl->zFwd = StrDup(StringGet(&str),0); StringReset(&str); StringInit(&str); StringAppend(&str,pList->zText,pList->nText); StringAppend(&str," ",0); StringAppend(&str,pName->zText,pName->nText); StringAppend(&str,";\n",2); pDecl->zFwdCpp = StrDup(StringGet(&str),0); StringReset(&str); if( flags & PS_Export ){ DeclSetProperty(pDecl,DP_Export); }else if( flags & PS_Local ){ DeclSetProperty(pDecl,DP_Local); } /* Here's something weird. ANSI-C doesn't allow a forward declaration ** of an enumeration. So we have to build the typedef into the ** definition. */ if( pDecl->zDecl && DeclHasProperty(pDecl, TY_Enumeration) ){ StringInit(&str); StringAppend(&str,pDecl->zDecl,0); StringAppend(&str,pDecl->zFwd,0); SafeFree(pDecl->zDecl); SafeFree(pDecl->zFwd); pDecl->zFwd = 0; pDecl->zDecl = StrDup(StringGet(&str),0); StringReset(&str); } if( pName->pNext->zText[0]==':' ){ DeclSetProperty(pDecl,DP_Cplusplus); } if( pName->nText==5 && strncmp(pName->zText,"class",5)==0 ){ DeclSetProperty(pDecl,DP_Cplusplus); } /* ** Remove all but pList and pName from the input stream. */ if( need_to_collapse ){ while( pEnd!=pName ){ Token *pPrev = pEnd->pPrev; pPrev->pNext = pEnd->pNext; pEnd->pNext->pPrev = pPrev; SafeFree(pEnd); pEnd = pPrev; } } return 0; } /* ** Given a list of tokens that declare something (a function, procedure, ** variable or typedef) find the token which contains the name of the ** thing being declared. ** ** Algorithm: ** ** The name is: ** ** 1. The first identifier that is followed by a "[", or ** ** 2. The first identifier that is followed by a "(" where the ** "(" is followed by another identifier, or ** ** 3. The first identifier followed by "::", or ** ** 4. If none of the above, then the last identifier. ** ** In all of the above, certain reserved words (like "char") are ** not considered identifiers. */ static Token *FindDeclName(Token *pFirst, Token *pLast){ Token *pName = 0; Token *p; int c; if( pFirst==0 || pLast==0 ){ return 0; } pLast = pLast->pNext; for(p=pFirst; p && p!=pLast; p=p->pNext){ if( p->eType==TT_Id ){ static IdentTable sReserved; static int isInit = 0; static char *aWords[] = { "char", "class", "const", "double", "enum", "extern", "EXPORT", "ET_PROC", "float", "int", "long", "PRIVATE", "PROTECTED", "PUBLIC", "register", "static", "struct", "sizeof", "signed", "typedef", "union", "volatile", "virtual", "void", }; if( !isInit ){ int i; for(i=0; izText,p->nText) ){ pName = p; } }else if( p==pFirst ){ continue; }else if( (c=p->zText[0])=='[' && pName ){ break; }else if( c=='(' && p->pNext && p->pNext->eType==TT_Id && pName ){ break; }else if( c==':' && p->zText[1]==':' && pName ){ break; } } return pName; } /* ** This routine is called when we see a method for a class that begins ** with the PUBLIC, PRIVATE, or PROTECTED keywords. Such methods are ** added to their class definitions. */ static int ProcessMethodDef(Token *pFirst, Token *pLast, int flags){ Token *pCode; Token *pClass; char *zDecl; Decl *pDecl; String str; int type; pCode = pLast; pLast = pLast->pPrev; while( pFirst->zText[0]=='P' ){ int rc = 1; switch( pFirst->nText ){ case 6: rc = strncmp(pFirst->zText,"PUBLIC",6); break; case 7: rc = strncmp(pFirst->zText,"PRIVATE",7); break; case 9: rc = strncmp(pFirst->zText,"PROTECTED",9); break; default: break; } if( rc ) break; pFirst = pFirst->pNext; } pClass = FindDeclName(pFirst,pLast); if( pClass==0 ){ fprintf(stderr,"%s:%d: Unable to find the class name for this method\n", zFilename, pFirst->nLine); return 1; } pDecl = FindDecl(pClass->zText, pClass->nText); if( pDecl==0 || (pDecl->flags & TY_Class)!=TY_Class ){ pDecl = CreateDecl(pClass->zText, pClass->nText); DeclSetProperty(pDecl, TY_Class); } StringInit(&str); if( pDecl->zExtra ){ StringAppend(&str, pDecl->zExtra, 0); SafeFree(pDecl->zExtra); pDecl->zExtra = 0; } type = flags & PS_PPP; if( pDecl->extraType!=type ){ if( type & PS_Public ){ StringAppend(&str, "public:\n", 0); pDecl->extraType = PS_Public; }else if( type & PS_Protected ){ StringAppend(&str, "protected:\n", 0); pDecl->extraType = PS_Protected; }else if( type & PS_Private ){ StringAppend(&str, "private:\n", 0); pDecl->extraType = PS_Private; } } StringAppend(&str, " ", 0); zDecl = TokensToString(pFirst, pLast, ";\n", pClass, 2); StringAppend(&str, zDecl, 0); SafeFree(zDecl); pDecl->zExtra = StrDup(StringGet(&str), 0); StringReset(&str); return 0; } /* ** This routine is called when we see a function or procedure definition. ** We make an entry in the declaration table that is a prototype for this ** function or procedure. */ static int ProcessProcedureDef(Token *pFirst, Token *pLast, int flags){ Token *pName; Decl *pDecl; Token *pCode; if( pFirst==0 || pLast==0 ){ return 0; } if( flags & PS_Method ){ if( flags & PS_PPP ){ return ProcessMethodDef(pFirst, pLast, flags); }else{ return 0; } } if( (flags & PS_Static)!=0 && !proto_static ){ return 0; } pCode = pLast; while( pLast && pLast!=pFirst && pLast->zText[0]!=')' ){ pLast = pLast->pPrev; } if( pLast==0 || pLast==pFirst || pFirst->pNext==pLast ){ fprintf(stderr,"%s:%d: Unrecognized syntax.\n", zFilename, pFirst->nLine); return 1; } if( flags & (PS_Interface|PS_Export|PS_Local) ){ fprintf(stderr,"%s:%d: Missing \"inline\" on function or procedure.\n", zFilename, pFirst->nLine); return 1; } pName = FindDeclName(pFirst,pLast); if( pName==0 ){ fprintf(stderr,"%s:%d: Malformed function or procedure definition.\n", zFilename, pFirst->nLine); return 1; } /* ** At this point we've isolated a procedure declaration between pFirst ** and pLast with the name pName. */ #ifdef DEBUG if( debugMask & PARSER ){ printf("**** Found routine: %.*s on line %d...\n", pName->nText, pName->zText, pFirst->nLine); PrintTokens(pFirst,pLast); printf(";\n"); } #endif pDecl = CreateDecl(pName->zText,pName->nText); pDecl->pComment = pFirst->pComment; if( pCode && pCode->eType==TT_Braces ){ pDecl->tokenCode = *pCode; } DeclSetProperty(pDecl,TY_Subroutine); pDecl->zDecl = TokensToString(pFirst,pLast,";\n",0,0); if( (flags & (PS_Static|PS_Local2))!=0 ){ DeclSetProperty(pDecl,DP_Local); }else if( (flags & (PS_Export2))!=0 ){ DeclSetProperty(pDecl,DP_Export); } if( flags & DP_Cplusplus ){ DeclSetProperty(pDecl,DP_Cplusplus); }else{ DeclSetProperty(pDecl,DP_ExternCReqd); } return 0; } /* ** This routine is called whenever we see the "inline" keyword. We ** need to seek-out the inline function or procedure and make a ** declaration out of the entire definition. */ static int ProcessInlineProc(Token *pFirst, int flags, int *pReset){ Token *pName; Token *pEnd; Decl *pDecl; for(pEnd=pFirst; pEnd; pEnd = pEnd->pNext){ if( pEnd->zText[0]=='{' || pEnd->zText[0]==';' ){ *pReset = pEnd->zText[0]; break; } } if( pEnd==0 ){ *pReset = ';'; fprintf(stderr,"%s:%d: incomplete inline procedure definition\n", zFilename, pFirst->nLine); return 1; } pName = FindDeclName(pFirst,pEnd); if( pName==0 ){ fprintf(stderr,"%s:%d: malformed inline procedure definition\n", zFilename, pFirst->nLine); return 1; } #ifdef DEBUG if( debugMask & PARSER ){ printf("**** Found inline routine: %.*s on line %d...\n", pName->nText, pName->zText, pFirst->nLine); PrintTokens(pFirst,pEnd); printf("\n"); } #endif pDecl = CreateDecl(pName->zText,pName->nText); pDecl->pComment = pFirst->pComment; DeclSetProperty(pDecl,TY_Subroutine); pDecl->zDecl = TokensToString(pFirst,pEnd,";\n",0,0); if( (flags & (PS_Static|PS_Local|PS_Local2)) ){ DeclSetProperty(pDecl,DP_Local); }else if( flags & (PS_Export|PS_Export2) ){ DeclSetProperty(pDecl,DP_Export); } if( flags & DP_Cplusplus ){ DeclSetProperty(pDecl,DP_Cplusplus); }else{ DeclSetProperty(pDecl,DP_ExternCReqd); } return 0; } /* ** Determine if the tokens between pFirst and pEnd form a variable ** definition or a function prototype. Return TRUE if we are dealing ** with a variable defintion and FALSE for a prototype. ** ** pEnd is the token that ends the object. It can be either a ';' or ** a '='. If it is '=', then assume we have a variable definition. ** ** If pEnd is ';', then the determination is more difficult. We have ** to search for an occurance of an ID followed immediately by '('. ** If found, we have a prototype. Otherwise we are dealing with a ** variable definition. */ static int isVariableDef(Token *pFirst, Token *pEnd){ if( pEnd && pEnd->zText[0]=='=' && (pEnd->pPrev->nText!=8 || strncmp(pEnd->pPrev->zText,"operator",8)!=0) ){ return 1; } while( pFirst && pFirst!=pEnd && pFirst->pNext && pFirst->pNext!=pEnd ){ if( pFirst->eType==TT_Id && pFirst->pNext->zText[0]=='(' ){ return 0; } pFirst = pFirst->pNext; } return 1; } /* ** This routine is called whenever we encounter a ";" or "=". The stuff ** between pFirst and pLast constitutes either a typedef or a global ** variable definition. Do the right thing. */ static int ProcessDecl(Token *pFirst, Token *pEnd, int flags){ Token *pName; Decl *pDecl; int isLocal = 0; int isVar; int nErr = 0; if( pFirst==0 || pEnd==0 ){ return 0; } if( flags & PS_Typedef ){ if( (flags & (PS_Export2|PS_Local2))!=0 ){ fprintf(stderr,"%s:%d: \"EXPORT\" or \"LOCAL\" ignored before typedef.\n", zFilename, pFirst->nLine); nErr++; } if( (flags & (PS_Interface|PS_Export|PS_Local|DP_Cplusplus))==0 ){ /* It is illegal to duplicate a typedef in C (but OK in C++). ** So don't record typedefs that aren't within a C++ file or ** within #if INTERFACE..#endif */ return nErr; } if( (flags & (PS_Interface|PS_Export|PS_Local))==0 && proto_static==0 ){ /* Ignore typedefs that are not with "#if INTERFACE..#endif" unless ** the "-local" command line option is used. */ return nErr; } if( (flags & (PS_Interface|PS_Export))==0 ){ /* typedefs are always local, unless within #if INTERFACE..#endif */ isLocal = 1; } }else if( flags & (PS_Static|PS_Local2) ){ if( proto_static==0 && (flags & PS_Local2)==0 ){ /* Don't record static variables unless the "-local" command line ** option was specified or the "LOCAL" keyword is used. */ return nErr; } while( pFirst!=0 && pFirst->pNext!=pEnd && ((pFirst->nText==6 && strncmp(pFirst->zText,"static",6)==0) || (pFirst->nText==5 && strncmp(pFirst->zText,"LOCAL",6)==0)) ){ /* Lose the initial "static" or local from local variables. ** We'll prepend "extern" later. */ pFirst = pFirst->pNext; isLocal = 1; } if( pFirst==0 || !isLocal ){ return nErr; } }else if( flags & PS_Method ){ /* Methods are declared by their class. Don't declare separately. */ return nErr; } isVar = (flags & (PS_Typedef|PS_Method))==0 && isVariableDef(pFirst,pEnd); if( isVar && (flags & (PS_Interface|PS_Export|PS_Local))!=0 && (flags & PS_Extern)==0 ){ fprintf(stderr,"%s:%d: Can't define a variable in this context\n", zFilename, pFirst->nLine); nErr++; } pName = FindDeclName(pFirst,pEnd->pPrev); if( pName==0 ){ fprintf(stderr,"%s:%d: Can't find a name for the object declared here.\n", zFilename, pFirst->nLine); return nErr+1; } #ifdef DEBUG if( debugMask & PARSER ){ if( flags & PS_Typedef ){ printf("**** Found typedef %.*s at line %d...\n", pName->nText, pName->zText, pName->nLine); }else if( isVar ){ printf("**** Found variable %.*s at line %d...\n", pName->nText, pName->zText, pName->nLine); }else{ printf("**** Found prototype %.*s at line %d...\n", pName->nText, pName->zText, pName->nLine); } PrintTokens(pFirst,pEnd->pPrev); printf(";\n"); } #endif pDecl = CreateDecl(pName->zText,pName->nText); if( (flags & PS_Typedef) ){ DeclSetProperty(pDecl, TY_Typedef); }else if( isVar ){ DeclSetProperty(pDecl,DP_ExternReqd | TY_Variable); if( !(flags & DP_Cplusplus) ){ DeclSetProperty(pDecl,DP_ExternCReqd); } }else{ DeclSetProperty(pDecl, TY_Subroutine); if( !(flags & DP_Cplusplus) ){ DeclSetProperty(pDecl,DP_ExternCReqd); } } pDecl->pComment = pFirst->pComment; pDecl->zDecl = TokensToString(pFirst,pEnd->pPrev,";\n",0,0); if( isLocal || (flags & (PS_Local|PS_Local2))!=0 ){ DeclSetProperty(pDecl,DP_Local); }else if( flags & (PS_Export|PS_Export2) ){ DeclSetProperty(pDecl,DP_Export); } if( flags & DP_Cplusplus ){ DeclSetProperty(pDecl,DP_Cplusplus); } return nErr; } /* ** Push an if condition onto the if stack */ static void PushIfMacro( const char *zPrefix, /* A prefix, like "define" or "!" */ const char *zText, /* The condition */ int nText, /* Number of characters in zText */ int nLine, /* Line number where this macro occurs */ int flags /* Either 0, PS_Interface, PS_Export or PS_Local */ ){ Ifmacro *pIf; int nByte; nByte = sizeof(Ifmacro); if( zText ){ if( zPrefix ){ nByte += strlen(zPrefix) + 2; } nByte += nText + 1; } pIf = SafeMalloc( nByte ); if( zText ){ pIf->zCondition = (char*)&pIf[1]; if( zPrefix ){ sprintf(pIf->zCondition,"%s(%.*s)",zPrefix,nText,zText); }else{ sprintf(pIf->zCondition,"%.*s",nText,zText); } }else{ pIf->zCondition = 0; } pIf->nLine = nLine; pIf->flags = flags; pIf->pNext = ifStack; ifStack = pIf; } /* ** This routine is called to handle all preprocessor directives. ** ** This routine will recompute the value of *pPresetFlags to be the ** logical or of all flags on all nested #ifs. The #ifs that set flags ** are as follows: ** ** conditional flag set ** ------------------------ -------------------- ** #if INTERFACE PS_Interface ** #if EXPORT_INTERFACE PS_Export ** #if LOCAL_INTERFACE PS_Local ** ** For example, if after processing the preprocessor token given ** by pToken there is an "#if INTERFACE" on the preprocessor ** stack, then *pPresetFlags will be set to PS_Interface. */ static int ParsePreprocessor(Token *pToken, int flags, int *pPresetFlags){ const char *zCmd; int nCmd; const char *zArg; int nArg; int nErr = 0; Ifmacro *pIf; zCmd = &pToken->zText[1]; while( isspace(*zCmd) && *zCmd!='\n' ){ zCmd++; } if( !isalpha(*zCmd) ){ return 0; } nCmd = 1; while( isalpha(zCmd[nCmd]) ){ nCmd++; } if( nCmd==5 && strncmp(zCmd,"endif",5)==0 ){ /* ** Pop the if stack */ pIf = ifStack; if( pIf==0 ){ fprintf(stderr,"%s:%d: extra '#endif'.\n",zFilename,pToken->nLine); return 1; } ifStack = pIf->pNext; SafeFree(pIf); }else if( nCmd==6 && strncmp(zCmd,"define",6)==0 ){ /* ** Record a #define if we are in PS_Interface or PS_Export */ Decl *pDecl; if( !(flags & (PS_Local|PS_Interface|PS_Export)) ){ return 0; } zArg = &zCmd[6]; while( *zArg && isspace(*zArg) && *zArg!='\n' ){ zArg++; } if( *zArg==0 || *zArg=='\n' ){ return 0; } for(nArg=0; ISALNUM(zArg[nArg]); nArg++){} if( nArg==0 ){ return 0; } pDecl = CreateDecl(zArg,nArg); pDecl->pComment = pToken->pComment; DeclSetProperty(pDecl,TY_Macro); pDecl->zDecl = SafeMalloc( pToken->nText + 2 ); sprintf(pDecl->zDecl,"%.*s\n",pToken->nText,pToken->zText); if( flags & PS_Export ){ DeclSetProperty(pDecl,DP_Export); }else if( flags & PS_Local ){ DeclSetProperty(pDecl,DP_Local); } }else if( nCmd==7 && strncmp(zCmd,"include",7)==0 ){ /* ** Record an #include if we are in PS_Interface or PS_Export */ Include *pInclude; char *zIf; if( !(flags & (PS_Interface|PS_Export)) ){ return 0; } zArg = &zCmd[7]; while( *zArg && isspace(*zArg) ){ zArg++; } for(nArg=0; !isspace(zArg[nArg]); nArg++){} if( (zArg[0]=='"' && zArg[nArg-1]!='"') ||(zArg[0]=='<' && zArg[nArg-1]!='>') ){ fprintf(stderr,"%s:%d: malformed #include statement.\n", zFilename,pToken->nLine); return 1; } zIf = GetIfString(); if( zIf ){ pInclude = SafeMalloc( sizeof(Include) + nArg*2 + strlen(zIf) + 10 ); pInclude->zFile = (char*)&pInclude[1]; pInclude->zLabel = &pInclude->zFile[nArg+1]; sprintf(pInclude->zFile,"%.*s",nArg,zArg); sprintf(pInclude->zLabel,"%.*s:%s",nArg,zArg,zIf); pInclude->zIf = &pInclude->zLabel[nArg+1]; SafeFree(zIf); }else{ pInclude = SafeMalloc( sizeof(Include) + nArg + 1 ); pInclude->zFile = (char*)&pInclude[1]; sprintf(pInclude->zFile,"%.*s",nArg,zArg); pInclude->zIf = 0; pInclude->zLabel = pInclude->zFile; } pInclude->pNext = includeList; includeList = pInclude; }else if( nCmd==2 && strncmp(zCmd,"if",2)==0 ){ /* ** Push an #if. Watch for the special cases of INTERFACE ** and EXPORT_INTERFACE and LOCAL_INTERFACE */ zArg = &zCmd[2]; while( *zArg && isspace(*zArg) && *zArg!='\n' ){ zArg++; } if( *zArg==0 || *zArg=='\n' ){ return 0; } nArg = pToken->nText + (int)(pToken->zText - zArg); if( nArg==9 && strncmp(zArg,"INTERFACE",9)==0 ){ PushIfMacro(0,0,0,pToken->nLine,PS_Interface); }else if( nArg==16 && strncmp(zArg,"EXPORT_INTERFACE",16)==0 ){ PushIfMacro(0,0,0,pToken->nLine,PS_Export); }else if( nArg==15 && strncmp(zArg,"LOCAL_INTERFACE",15)==0 ){ PushIfMacro(0,0,0,pToken->nLine,PS_Local); }else{ PushIfMacro(0,zArg,nArg,pToken->nLine,0); } }else if( nCmd==5 && strncmp(zCmd,"ifdef",5)==0 ){ /* ** Push an #ifdef. */ zArg = &zCmd[5]; while( *zArg && isspace(*zArg) && *zArg!='\n' ){ zArg++; } if( *zArg==0 || *zArg=='\n' ){ return 0; } nArg = pToken->nText + (int)(pToken->zText - zArg); PushIfMacro("defined",zArg,nArg,pToken->nLine,0); }else if( nCmd==6 && strncmp(zCmd,"ifndef",6)==0 ){ /* ** Push an #ifndef. */ zArg = &zCmd[6]; while( *zArg && isspace(*zArg) && *zArg!='\n' ){ zArg++; } if( *zArg==0 || *zArg=='\n' ){ return 0; } nArg = pToken->nText + (int)(pToken->zText - zArg); PushIfMacro("!defined",zArg,nArg,pToken->nLine,0); }else if( nCmd==4 && strncmp(zCmd,"else",4)==0 ){ /* ** Invert the #if on the top of the stack */ if( ifStack==0 ){ fprintf(stderr,"%s:%d: '#else' without an '#if'\n",zFilename, pToken->nLine); return 1; } pIf = ifStack; if( pIf->zCondition ){ ifStack = ifStack->pNext; PushIfMacro("!",pIf->zCondition,strlen(pIf->zCondition),pIf->nLine,0); SafeFree(pIf); }else{ pIf->flags = 0; } }else{ /* ** This directive can be safely ignored */ return 0; } /* ** Recompute the preset flags */ *pPresetFlags = 0; for(pIf = ifStack; pIf; pIf=pIf->pNext){ *pPresetFlags |= pIf->flags; } return nErr; } /* ** Parse an entire file. Return the number of errors. ** ** pList is a list of tokens in the file. Whitespace tokens have been ** eliminated, and text with {...} has been collapsed into a ** single TT_Brace token. ** ** initFlags are a set of parse flags that should always be set for this ** file. For .c files this is normally 0. For .h files it is PS_Interface. */ static int ParseFile(Token *pList, int initFlags){ int nErr = 0; Token *pStart = 0; int flags = initFlags; int presetFlags = initFlags; int resetFlag = 0; includeList = 0; while( pList ){ switch( pList->eType ){ case TT_EOF: goto end_of_loop; case TT_Preprocessor: nErr += ParsePreprocessor(pList,flags,&presetFlags); pStart = 0; presetFlags |= initFlags; flags = presetFlags; break; case TT_Other: switch( pList->zText[0] ){ case ';': nErr += ProcessDecl(pStart,pList,flags); pStart = 0; flags = presetFlags; break; case '=': if( pList->pPrev->nText==8 && strncmp(pList->pPrev->zText,"operator",8)==0 ){ break; } nErr += ProcessDecl(pStart,pList,flags); pStart = 0; while( pList && pList->zText[0]!=';' ){ pList = pList->pNext; } if( pList==0 ) goto end_of_loop; flags = presetFlags; break; case ':': if( pList->zText[1]==':' ){ flags |= PS_Method; } break; default: break; } break; case TT_Braces: nErr += ProcessProcedureDef(pStart,pList,flags); pStart = 0; flags = presetFlags; break; case TT_Id: if( pStart==0 ){ pStart = pList; flags = presetFlags; } resetFlag = 0; switch( pList->zText[0] ){ case 'c': if( pList->nText==5 && strncmp(pList->zText,"class",5)==0 ){ nErr += ProcessTypeDecl(pList,flags,&resetFlag); } break; case 'E': if( pList->nText==6 && strncmp(pList->zText,"EXPORT",6)==0 ){ flags |= PS_Export2; /* pStart = 0; */ } break; case 'e': if( pList->nText==4 && strncmp(pList->zText,"enum",4)==0 ){ if( pList->pNext && pList->pNext->eType==TT_Braces ){ pList = pList->pNext; }else{ nErr += ProcessTypeDecl(pList,flags,&resetFlag); } }else if( pList->nText==6 && strncmp(pList->zText,"extern",6)==0 ){ pList = pList->pNext; if( pList && pList->nText==3 && strncmp(pList->zText,"\"C\"",3)==0 ){ pList = pList->pNext; flags &= ~DP_Cplusplus; }else{ flags |= PS_Extern; } pStart = pList; } break; case 'i': if( pList->nText==6 && strncmp(pList->zText,"inline",6)==0 ){ nErr += ProcessInlineProc(pList,flags,&resetFlag); } break; case 'L': if( pList->nText==5 && strncmp(pList->zText,"LOCAL",5)==0 ){ flags |= PS_Local2; pStart = pList; } break; case 'P': if( pList->nText==6 && strncmp(pList->zText, "PUBLIC",6)==0 ){ flags |= PS_Public; pStart = pList; }else if( pList->nText==7 && strncmp(pList->zText, "PRIVATE",7)==0 ){ flags |= PS_Private; pStart = pList; }else if( pList->nText==9 && strncmp(pList->zText,"PROTECTED",9)==0 ){ flags |= PS_Protected; pStart = pList; } break; case 's': if( pList->nText==6 && strncmp(pList->zText,"struct",6)==0 ){ if( pList->pNext && pList->pNext->eType==TT_Braces ){ pList = pList->pNext; }else{ nErr += ProcessTypeDecl(pList,flags,&resetFlag); } }else if( pList->nText==6 && strncmp(pList->zText,"static",6)==0 ){ flags |= PS_Static; } break; case 't': if( pList->nText==7 && strncmp(pList->zText,"typedef",7)==0 ){ flags |= PS_Typedef; } break; case 'u': if( pList->nText==5 && strncmp(pList->zText,"union",5)==0 ){ if( pList->pNext && pList->pNext->eType==TT_Braces ){ pList = pList->pNext; }else{ nErr += ProcessTypeDecl(pList,flags,&resetFlag); } } break; default: break; } if( resetFlag!=0 ){ while( pList && pList->zText[0]!=resetFlag ){ pList = pList->pNext; } if( pList==0 ) goto end_of_loop; pStart = 0; flags = presetFlags; } break; case TT_String: case TT_Number: break; default: pStart = pList; flags = presetFlags; break; } pList = pList->pNext; } end_of_loop: /* Verify that all #ifs have a matching "#endif" */ while( ifStack ){ Ifmacro *pIf = ifStack; ifStack = pIf->pNext; fprintf(stderr,"%s:%d: This '#if' has no '#endif'\n",zFilename, pIf->nLine); SafeFree(pIf); } return nErr; } /* ** If the given Decl object has a non-null zExtra field, then the text ** of that zExtra field needs to be inserted in the middle of the ** zDecl field before the last "}" in the zDecl. This routine does that. ** If the zExtra is NULL, this routine is a no-op. ** ** zExtra holds extra method declarations for classes. The declarations ** have to be inserted into the class definition. */ static void InsertExtraDecl(Decl *pDecl){ int i; String str; if( pDecl==0 || pDecl->zExtra==0 || pDecl->zDecl==0 ) return; i = strlen(pDecl->zDecl) - 1; while( i>0 && pDecl->zDecl[i]!='}' ){ i--; } StringInit(&str); StringAppend(&str, pDecl->zDecl, i); StringAppend(&str, pDecl->zExtra, 0); StringAppend(&str, &pDecl->zDecl[i], 0); SafeFree(pDecl->zDecl); SafeFree(pDecl->zExtra); pDecl->zDecl = StrDup(StringGet(&str), 0); StringReset(&str); pDecl->zExtra = 0; } /* ** Reset the DP_Forward and DP_Declared flags on all Decl structures. ** Set both flags for anything that is tagged as local and isn't ** in the file zFilename so that it won't be printing in other files. */ static void ResetDeclFlags(char *zFilename){ Decl *pDecl; for(pDecl = pDeclFirst; pDecl; pDecl = pDecl->pNext){ DeclClearProperty(pDecl,DP_Forward|DP_Declared); if( DeclHasProperty(pDecl,DP_Local) && pDecl->zFile!=zFilename ){ DeclSetProperty(pDecl,DP_Forward|DP_Declared); } } } /* ** Forward declaration of the ScanText() function. */ static void ScanText(const char*, GenState *pState); /* ** The output in pStr is currently within an #if CONTEXT where context ** is equal to *pzIf. (*pzIf might be NULL to indicate that we are ** not within any #if at the moment.) We are getting ready to output ** some text that needs to be within the context of "#if NEW" where ** NEW is zIf. Make an appropriate change to the context. */ static void ChangeIfContext( const char *zIf, /* The desired #if context */ GenState *pState /* Current state of the code generator */ ){ if( zIf==0 ){ if( pState->zIf==0 ) return; StringAppend(pState->pStr,"#endif\n",0); pState->zIf = 0; }else{ if( pState->zIf ){ if( strcmp(zIf,pState->zIf)==0 ) return; StringAppend(pState->pStr,"#endif\n",0); pState->zIf = 0; } ScanText(zIf, pState); if( pState->zIf!=0 ){ StringAppend(pState->pStr,"#endif\n",0); } StringAppend(pState->pStr,"#if ",0); StringAppend(pState->pStr,zIf,0); StringAppend(pState->pStr,"\n",0); pState->zIf = zIf; } } /* ** Add to the string pStr a #include of every file on the list of ** include files pInclude. The table pTable contains all files that ** have already been #included at least once. Don't add any ** duplicates. Update pTable with every new #include that is added. */ static void AddIncludes( Include *pInclude, /* Write every #include on this list */ GenState *pState /* Current state of the code generator */ ){ if( pInclude ){ if( pInclude->pNext ){ AddIncludes(pInclude->pNext,pState); } if( IdentTableInsert(pState->pTable,pInclude->zLabel,0) ){ ChangeIfContext(pInclude->zIf,pState); StringAppend(pState->pStr,"#include ",0); StringAppend(pState->pStr,pInclude->zFile,0); StringAppend(pState->pStr,"\n",1); } } } /* ** Add to the string pStr a declaration for the object described ** in pDecl. ** ** If pDecl has already been declared in this file, detect that ** fact and abort early. Do not duplicate a declaration. ** ** If the needFullDecl flag is false and this object has a forward ** declaration, then supply the forward declaration only. A later ** call to CompleteForwardDeclarations() will finish the declaration ** for us. But if needFullDecl is true, we must supply the full ** declaration now. Some objects do not have a forward declaration. ** For those objects, we must print the full declaration now. ** ** Because it is illegal to duplicate a typedef in C, care is taken ** to insure that typedefs for the same identifier are only issued once. */ static void DeclareObject( Decl *pDecl, /* The thing to be declared */ GenState *pState, /* Current state of the code generator */ int needFullDecl /* Must have the full declaration. A forward * declaration isn't enough */ ){ Decl *p; /* The object to be declared */ int flag; int isCpp; /* True if generating C++ */ int doneTypedef = 0; /* True if a typedef has been done for this object */ /* printf("BEGIN %s of %s\n",needFullDecl?"FULL":"PROTOTYPE",pDecl->zName);*/ /* ** For any object that has a forward declaration, go ahead and do the ** forward declaration first. */ isCpp = (pState->flags & DP_Cplusplus) != 0; for(p=pDecl; p; p=p->pSameName){ if( p->zFwd ){ if( !DeclHasProperty(p,DP_Forward) ){ DeclSetProperty(p,DP_Forward); if( strncmp(p->zFwd,"typedef",7)==0 ){ if( doneTypedef ) continue; doneTypedef = 1; } ChangeIfContext(p->zIf,pState); StringAppend(pState->pStr,isCpp ? p->zFwdCpp : p->zFwd,0); } } } /* ** Early out if everything is already suitably declared. ** ** This is a very important step because it prevents us from ** executing the code the follows in a recursive call to this ** function with the same value for pDecl. */ flag = needFullDecl ? DP_Declared|DP_Forward : DP_Forward; for(p=pDecl; p; p=p->pSameName){ if( !DeclHasProperty(p,flag) ) break; } if( p==0 ){ return; } /* ** Make sure we have all necessary #includes */ for(p=pDecl; p; p=p->pSameName){ AddIncludes(p->pInclude,pState); } /* ** Go ahead an mark everything as being declared, to prevent an ** infinite loop thru the ScanText() function. At the same time, ** we decide which objects need a full declaration and mark them ** with the DP_Flag bit. We are only able to use DP_Flag in this ** way because we know we'll never execute this far into this ** function on a recursive call with the same pDecl. Hence, recursive ** calls to this function (through ScanText()) can never change the ** value of DP_Flag out from under us. */ for(p=pDecl; p; p=p->pSameName){ if( !DeclHasProperty(p,DP_Declared) && (p->zFwd==0 || needFullDecl) && p->zDecl!=0 ){ DeclSetProperty(p,DP_Forward|DP_Declared|DP_Flag); }else{ DeclClearProperty(p,DP_Flag); } } /* ** Call ScanText() recusively (this routine is called from ScanText()) ** to include declarations required to come before these declarations. */ for(p=pDecl; p; p=p->pSameName){ if( DeclHasProperty(p,DP_Flag) ){ if( p->zDecl[0]=='#' ){ ScanText(&p->zDecl[1],pState); }else{ InsertExtraDecl(p); ScanText(p->zDecl,pState); } } } /* ** Output the declarations. Do this in two passes. First ** output everything that isn't a typedef. Then go back and ** get the typedefs by the same name. */ for(p=pDecl; p; p=p->pSameName){ if( DeclHasProperty(p,DP_Flag) && !DeclHasProperty(p,TY_Typedef) ){ if( DeclHasAnyProperty(p,TY_Enumeration) ){ if( doneTypedef ) continue; doneTypedef = 1; } ChangeIfContext(p->zIf,pState); if( !isCpp && DeclHasAnyProperty(p,DP_ExternReqd) ){ StringAppend(pState->pStr,"extern ",0); }else if( isCpp && DeclHasProperty(p,DP_Cplusplus|DP_ExternReqd) ){ StringAppend(pState->pStr,"extern ",0); }else if( isCpp && DeclHasAnyProperty(p,DP_ExternCReqd|DP_ExternReqd) ){ StringAppend(pState->pStr,"extern \"C\" ",0); } InsertExtraDecl(p); StringAppend(pState->pStr,p->zDecl,0); if( !isCpp && DeclHasProperty(p,DP_Cplusplus) ){ fprintf(stderr, "%s: C code ought not reference the C++ object \"%s\"\n", pState->zFilename, p->zName); pState->nErr++; } DeclClearProperty(p,DP_Flag); } } for(p=pDecl; p && !doneTypedef; p=p->pSameName){ if( DeclHasProperty(p,DP_Flag) ){ /* This has to be a typedef */ doneTypedef = 1; ChangeIfContext(p->zIf,pState); InsertExtraDecl(p); StringAppend(pState->pStr,p->zDecl,0); } } } /* ** This routine scans the input text given, and appends to the ** string in pState->pStr the text of any declarations that must ** occur before the text in zText. ** ** If an identifier in zText is immediately followed by '*', then ** only forward declarations are needed for that identifier. If the ** identifier name is not followed immediately by '*', we must supply ** a full declaration. */ static void ScanText( const char *zText, /* The input text to be scanned */ GenState *pState /* Current state of the code generator */ ){ int nextValid = 0; /* True is sNext contains valid data */ InStream sIn; /* The input text */ Token sToken; /* The current token being examined */ Token sNext; /* The next non-space token */ /* printf("BEGIN SCAN TEXT on %s\n", zText); */ sIn.z = zText; sIn.i = 0; sIn.nLine = 1; while( sIn.z[sIn.i]!=0 ){ if( nextValid ){ sToken = sNext; nextValid = 0; }else{ GetNonspaceToken(&sIn,&sToken); } if( sToken.eType==TT_Id ){ int needFullDecl; /* True if we need to provide the full declaration, ** not just the forward declaration */ Decl *pDecl; /* The declaration having the name in sToken */ /* ** See if there is a declaration in the database with the name given ** by sToken. */ pDecl = FindDecl(sToken.zText,sToken.nText); if( pDecl==0 ) continue; /* ** If we get this far, we've found an identifier that has a ** declaration in the database. Now see if we the full declaration ** or just a forward declaration. */ GetNonspaceToken(&sIn,&sNext); if( sNext.zText[0]=='*' ){ needFullDecl = 0; }else{ needFullDecl = 1; nextValid = sNext.eType==TT_Id; } /* ** Generate the needed declaration. */ DeclareObject(pDecl,pState,needFullDecl); }else if( sToken.eType==TT_Preprocessor ){ sIn.i -= sToken.nText - 1; } } /* printf("END SCANTEXT\n"); */ } /* ** Provide a full declaration to any object which so far has had only ** a foward declaration. */ static void CompleteForwardDeclarations(GenState *pState){ Decl *pDecl; int progress; do{ progress = 0; for(pDecl=pDeclFirst; pDecl; pDecl=pDecl->pNext){ if( DeclHasProperty(pDecl,DP_Forward) && !DeclHasProperty(pDecl,DP_Declared) ){ DeclareObject(pDecl,pState,1); progress = 1; assert( DeclHasProperty(pDecl,DP_Declared) ); } } }while( progress ); } /* ** Generate an include file for the given source file. Return the number ** of errors encountered. ** ** if nolocal_flag is true, then we do not generate declarations for ** objected marked DP_Local. */ static int MakeHeader(InFile *pFile, FILE *report, int nolocal_flag){ int nErr = 0; GenState sState; String outStr; IdentTable includeTable; Ident *pId; char *zNewVersion; char *zOldVersion; if( pFile->zHdr==0 || *pFile->zHdr==0 ) return 0; sState.pStr = &outStr; StringInit(&outStr); StringAppend(&outStr,zTopLine,nTopLine); sState.pTable = &includeTable; memset(&includeTable,0,sizeof(includeTable)); sState.zIf = 0; sState.nErr = 0; sState.zFilename = pFile->zSrc; sState.flags = pFile->flags & DP_Cplusplus; ResetDeclFlags(nolocal_flag ? "no" : pFile->zSrc); for(pId = pFile->idTable.pList; pId; pId=pId->pNext){ Decl *pDecl = FindDecl(pId->zName,0); if( pDecl ){ DeclareObject(pDecl,&sState,1); } } CompleteForwardDeclarations(&sState); ChangeIfContext(0,&sState); nErr += sState.nErr; zOldVersion = ReadFile(pFile->zHdr); zNewVersion = StringGet(&outStr); if( report ) fprintf(report,"%s: ",pFile->zHdr); if( zOldVersion==0 ){ if( report ) fprintf(report,"updated\n"); if( WriteFile(pFile->zHdr,zNewVersion) ){ fprintf(stderr,"%s: Can't write to file\n",pFile->zHdr); nErr++; } }else if( strncmp(zOldVersion,zTopLine,nTopLine)!=0 ){ if( report ) fprintf(report,"error!\n"); fprintf(stderr, "%s: Can't overwrite this file because it wasn't previously\n" "%*s generated by 'makeheaders'.\n", pFile->zHdr, (int)strlen(pFile->zHdr), ""); nErr++; }else if( strcmp(zOldVersion,zNewVersion)!=0 ){ if( report ) fprintf(report,"updated\n"); if( WriteFile(pFile->zHdr,zNewVersion) ){ fprintf(stderr,"%s: Can't write to file\n",pFile->zHdr); nErr++; } }else if( report ){ fprintf(report,"unchanged\n"); } SafeFree(zOldVersion); IdentTableReset(&includeTable); StringReset(&outStr); return nErr; } /* ** Generate a global header file -- a header file that contains all ** declarations. If the forExport flag is true, then only those ** objects that are exported are included in the header file. */ static int MakeGlobalHeader(int forExport){ GenState sState; String outStr; IdentTable includeTable; Decl *pDecl; sState.pStr = &outStr; StringInit(&outStr); /* StringAppend(&outStr,zTopLine,nTopLine); */ sState.pTable = &includeTable; memset(&includeTable,0,sizeof(includeTable)); sState.zIf = 0; sState.nErr = 0; sState.zFilename = "(all)"; sState.flags = 0; ResetDeclFlags(0); for(pDecl=pDeclFirst; pDecl; pDecl=pDecl->pNext){ if( forExport==0 || DeclHasProperty(pDecl,DP_Export) ){ DeclareObject(pDecl,&sState,1); } } ChangeIfContext(0,&sState); printf("%s",StringGet(&outStr)); IdentTableReset(&includeTable); StringReset(&outStr); return 0; } #ifdef DEBUG /* ** Return the number of characters in the given string prior to the ** first newline. */ static int ClipTrailingNewline(char *z){ int n = strlen(z); while( n>0 && (z[n-1]=='\n' || z[n-1]=='\r') ){ n--; } return n; } /* ** Dump the entire declaration list for debugging purposes */ static void DumpDeclList(void){ Decl *pDecl; for(pDecl = pDeclFirst; pDecl; pDecl=pDecl->pNext){ printf("**** %s from file %s ****\n",pDecl->zName,pDecl->zFile); if( pDecl->zIf ){ printf("If: [%.*s]\n",ClipTrailingNewline(pDecl->zIf),pDecl->zIf); } if( pDecl->zFwd ){ printf("Decl: [%.*s]\n",ClipTrailingNewline(pDecl->zFwd),pDecl->zFwd); } if( pDecl->zDecl ){ InsertExtraDecl(pDecl); printf("Def: [%.*s]\n",ClipTrailingNewline(pDecl->zDecl),pDecl->zDecl); } if( pDecl->flags ){ static struct { int mask; char *desc; } flagSet[] = { { TY_Class, "class" }, { TY_Enumeration, "enum" }, { TY_Structure, "struct" }, { TY_Union, "union" }, { TY_Variable, "variable" }, { TY_Subroutine, "function" }, { TY_Typedef, "typedef" }, { TY_Macro, "macro" }, { DP_Export, "export" }, { DP_Local, "local" }, { DP_Cplusplus, "C++" }, }; int i; printf("flags:"); for(i=0; iflags ){ printf(" %s", flagSet[i].desc); } } printf("\n"); } if( pDecl->pInclude ){ Include *p; printf("includes:"); for(p=pDecl->pInclude; p; p=p->pNext){ printf(" %s",p->zFile); } printf("\n"); } } } #endif /* ** When the "-doc" command-line option is used, this routine is called ** to print all of the database information to standard output. */ static void DocumentationDump(void){ Decl *pDecl; static struct { int mask; char flag; } flagSet[] = { { TY_Class, 'c' }, { TY_Enumeration, 'e' }, { TY_Structure, 's' }, { TY_Union, 'u' }, { TY_Variable, 'v' }, { TY_Subroutine, 'f' }, { TY_Typedef, 't' }, { TY_Macro, 'm' }, { DP_Export, 'x' }, { DP_Local, 'l' }, { DP_Cplusplus, '+' }, }; for(pDecl = pDeclFirst; pDecl; pDecl=pDecl->pNext){ int i; int nLabel = 0; char *zDecl; char zLabel[50]; for(i=0; izDecl; if( zDecl==0 ) zDecl = pDecl->zFwd; printf("%s %s %s %p %d %d %d %d %d\n", pDecl->zName, zLabel, pDecl->zFile, pDecl->pComment, pDecl->pComment ? pDecl->pComment->nText+1 : 0, pDecl->zIf ? (int)strlen(pDecl->zIf)+1 : 0, zDecl ? (int)strlen(zDecl) : 0, pDecl->pComment ? pDecl->pComment->nLine : 0, pDecl->tokenCode.nText ? pDecl->tokenCode.nText+1 : 0 ); if( pDecl->pComment ){ printf("%.*s\n",pDecl->pComment->nText, pDecl->pComment->zText); } if( pDecl->zIf ){ printf("%s\n",pDecl->zIf); } if( zDecl ){ printf("%s",zDecl); } if( pDecl->tokenCode.nText ){ printf("%.*s\n",pDecl->tokenCode.nText, pDecl->tokenCode.zText); } } } /* ** Given the complete text of an input file, this routine prints a ** documentation record for the header comment at the beginning of the ** file (if the file has a header comment.) */ void PrintModuleRecord(const char *zFile, const char *zFilename){ int i; static int addr = 5; while( isspace(*zFile) ){ zFile++; } if( *zFile!='/' || zFile[1]!='*' ) return; for(i=2; zFile[i] && (zFile[i-1]!='/' || zFile[i-2]!='*'); i++){} if( zFile[i]==0 ) return; printf("%s M %s %d %d 0 0 0 0\n%.*s\n", zFilename, zFilename, addr, i+1, i, zFile); addr += 4; } /* ** Given an input argument to the program, construct a new InFile ** object. */ static InFile *CreateInFile(char *zArg, int *pnErr){ int nSrc; char *zSrc; InFile *pFile; int i; /* ** Get the name of the input file to be scanned. The input file is ** everything before the first ':' or the whole file if no ':' is seen. ** ** Except, on windows, ignore any ':' that occurs as the second character ** since it might be part of the drive specifier. So really, the ":' has ** to be the 3rd or later character in the name. This precludes 1-character ** file names, which really should not be a problem. */ zSrc = zArg; for(nSrc=2; zSrc[nSrc] && zArg[nSrc]!=':'; nSrc++){} pFile = SafeMalloc( sizeof(InFile) ); memset(pFile,0,sizeof(InFile)); pFile->zSrc = StrDup(zSrc,nSrc); /* Figure out if we are dealing with C or C++ code. Assume any ** file with ".c" or ".h" is C code and all else is C++. */ if( nSrc>2 && zSrc[nSrc-2]=='.' && (zSrc[nSrc-1]=='c' || zSrc[nSrc-1]=='h' || zSrc[nSrc-1]=='m')){ pFile->flags &= ~DP_Cplusplus; }else{ pFile->flags |= DP_Cplusplus; } /* ** If a separate header file is specified, use it */ if( zSrc[nSrc]==':' ){ int nHdr; char *zHdr; zHdr = &zSrc[nSrc+1]; for(nHdr=0; zHdr[nHdr] && zHdr[nHdr]!=':'; nHdr++){} pFile->zHdr = StrDup(zHdr,nHdr); } /* Look for any 'c' or 'C' in the suffix of the file name and change ** that character to 'h' or 'H' respectively. If no 'c' or 'C' is found, ** then assume we are dealing with a header. */ else{ int foundC = 0; pFile->zHdr = StrDup(zSrc,nSrc); for(i = nSrc-1; i>0 && pFile->zHdr[i]!='.'; i--){ if( pFile->zHdr[i]=='c' || pFile->zHdr[i]=='m' ){ foundC = 1; pFile->zHdr[i] = 'h'; }else if( pFile->zHdr[i]=='C' ){ foundC = 1; pFile->zHdr[i] = 'H'; } } if( !foundC ){ SafeFree(pFile->zHdr); pFile->zHdr = 0; } } /* ** If pFile->zSrc contains no 'c' or 'C' in its extension, it ** must be a header file. In that case, we need to set the ** PS_Interface flag. */ pFile->flags |= PS_Interface; for(i=nSrc-1; i>0 && zSrc[i]!='.'; i--){ if( zSrc[i]=='c' || zSrc[i]=='C' || zSrc[i]=='m' ){ pFile->flags &= ~PS_Interface; break; } } /* Done! */ return pFile; } /* MS-Windows and MS-DOS both have the following serious OS bug: the ** length of a command line is severely restricted. But this program ** occasionally requires long command lines. Hence the following ** work around. ** ** If the parameters "-f FILENAME" appear anywhere on the command line, ** then the named file is scanned for additional command line arguments. ** These arguments are substituted in place of the "FILENAME" argument ** in the original argument list. ** ** This first parameter to this routine is the index of the "-f" ** parameter in the argv[] array. The argc and argv are passed by ** pointer so that they can be changed. ** ** Parsing of the parameters in the file is very simple. Parameters ** can be separated by any amount of white-space (including newlines ** and carriage returns.) There are now quoting characters of any ** kind. The length of a token is limited to about 1000 characters. */ static void AddParameters(int index, int *pArgc, char ***pArgv){ int argc = *pArgc; /* The original argc value */ char **argv = *pArgv; /* The original argv value */ int newArgc; /* Value for argc after inserting new arguments */ char **zNew = 0; /* The new argv after this routine is done */ char *zFile; /* Name of the input file */ int nNew = 0; /* Number of new entries in the argv[] file */ int nAlloc = 0; /* Space allocated for zNew[] */ int i; /* Loop counter */ int n; /* Number of characters in a new argument */ int c; /* Next character of input */ int startOfLine = 1; /* True if we are where '#' can start a comment */ FILE *in; /* The input file */ char zBuf[1000]; /* A single argument is accumulated here */ if( index+1==argc ) return; zFile = argv[index+1]; in = fopen(zFile,"r"); if( in==0 ){ fprintf(stderr,"Can't open input file \"%s\"\n",zFile); exit(1); } c = ' '; while( c!=EOF ){ while( c!=EOF && isspace(c) ){ if( c=='\n' ){ startOfLine = 1; } c = getc(in); if( startOfLine && c=='#' ){ while( c!=EOF && c!='\n' ){ c = getc(in); } } } n = 0; while( c!=EOF && !isspace(c) ){ if( n0 ){ nNew++; if( nNew + argc > nAlloc ){ if( nAlloc==0 ){ nAlloc = 100 + argc; zNew = malloc( sizeof(char*) * nAlloc ); }else{ nAlloc *= 2; zNew = realloc( zNew, sizeof(char*) * nAlloc ); } } if( zNew ){ int j = nNew + index; zNew[j] = malloc( n + 1 ); if( zNew[j] ){ strcpy( zNew[j], zBuf ); } } } } newArgc = argc + nNew - 1; for(i=0; i<=index; i++){ zNew[i] = argv[i]; } for(i=nNew + index + 1; ipNext = pFile; pTail = pFile; }else{ pFileList = pTail = pFile; } } } } if( h_flag && H_flag ){ h_flag = 0; } if( v_flag ){ report = (h_flag || H_flag) ? stderr : stdout; }else{ report = 0; } if( nErr>0 ){ return nErr; } for(pFile=pFileList; pFile; pFile=pFile->pNext){ char *zFile; zFilename = pFile->zSrc; if( zFilename==0 ) continue; zFile = ReadFile(zFilename); if( zFile==0 ){ fprintf(stderr,"Can't read input file \"%s\"\n",zFilename); nErr++; continue; } if( strncmp(zFile,zTopLine,nTopLine)==0 ){ pFile->zSrc = 0; }else{ if( report ) fprintf(report,"Reading %s...\n",zFilename); pList = TokenizeFile(zFile,&pFile->idTable); if( pList ){ nErr += ParseFile(pList,pFile->flags); FreeTokenList(pList); }else if( zFile[0]==0 ){ fprintf(stderr,"Input file \"%s\" is empty.\n", zFilename); nErr++; }else{ fprintf(stderr,"Errors while processing \"%s\"\n", zFilename); nErr++; } } if( !doc_flag ) SafeFree(zFile); if( doc_flag ) PrintModuleRecord(zFile,zFilename); } if( nErr>0 ){ return nErr; } #ifdef DEBUG if( debugMask & DECL_DUMP ){ DumpDeclList(); return nErr; } #endif if( doc_flag ){ DocumentationDump(); return nErr; } zFilename = "--internal--"; pList = TokenizeFile(zInit,0); if( pList==0 ){ return nErr+1; } ParseFile(pList,PS_Interface); FreeTokenList(pList); if( h_flag || H_flag ){ nErr += MakeGlobalHeader(H_flag); }else{ for(pFile=pFileList; pFile; pFile=pFile->pNext){ if( pFile->zSrc==0 ) continue; nErr += MakeHeader(pFile,report,0); } } return nErr; } #endif openvpn-auth-ldap-auth-ldap-2.0.4/ubuntu_16.04_lts_build.sh000077500000000000000000000006221332642612100234060ustar00rootroot00000000000000#! /bin/bash # git clone https://github.com/snowrider311/openvpn-auth-ldap # cd openvpn-auth-ldap/ # source ubuntu_16.04_lts_build.sh # source ubuntu_16.04_lts_package.sh sudo apt-get update sudo apt-get -y install openvpn autoconf re2c libtool libldap2-dev libssl-dev gobjc make ./regen.sh ./configure --with-openvpn=/usr/include/openvpn CFLAGS="-fPIC" OBJCFLAGS="-std=gnu11" make sudo make install openvpn-auth-ldap-auth-ldap-2.0.4/ubuntu_16.04_lts_package.sh000077500000000000000000000011331332642612100237000ustar00rootroot00000000000000#! /bin/bash sudo apt-get install -y ruby ruby-dev rubygems build-essential sudo gem install --no-ri --no-rdoc fpm mkdir -p /tmp/openvpn-auth-ldap-build/usr/lib/openvpn sudo mv /usr/local/lib/openvpn-auth-ldap.so /tmp/openvpn-auth-ldap-build/usr/lib/openvpn fpm -s dir -C /tmp/openvpn-auth-ldap-build -t deb --name openvpn-auth-ldap-snowrider311 \ --version 2.0.3 --iteration 1 --depends openvpn --depends gnustep-base-runtime \ --depends libc6 --depends libgnustep-base1.24 --depends libldap-2.4-2 --depends libobjc4 # To install: # sudo dpkg -i openvpn-auth-ldap-snowrider311_2.0.3-1_amd64.deb