/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) Microsoft Corporation // // SYNOPSIS // // Defines the class RadiusExtensionPoint // /////////////////////////////////////////////////////////////////////////////// #include "Precompiled.h" #include "ias.h" #include "ExtensionPoint.h" #include "Extension.h" #include RadiusExtensionPoint::RadiusExtensionPoint() throw () : name(L""), begin(0), end(0) { } RadiusExtensionPoint::~RadiusExtensionPoint() throw () { delete[] begin; } DWORD RadiusExtensionPoint::Load(RADIUS_EXTENSION_POINT whichDlls) throw () { DWORD status = NO_ERROR; HKEY key = 0; bool ignoreFindNotFound = true; do { name = (whichDlls == repAuthentication) ? AUTHSRV_EXTENSIONS_VALUE_W : AUTHSRV_AUTHORIZATION_VALUE_W; IASTracePrintf("Loading %S", name); // Open the registry key. status = RegOpenKeyW( HKEY_LOCAL_MACHINE, AUTHSRV_PARAMETERS_KEY_W, &key ); if (status != NO_ERROR) { if (status == ERROR_FILE_NOT_FOUND) { IASTracePrintf( "%S doesn't exist; no extensions loaded.", AUTHSRV_PARAMETERS_KEY_W ); } else { IASTracePrintf( "RegOpenKeyW for %S failed with error %ld.", AUTHSRV_PARAMETERS_KEY_W, status ); } break; } // Allocate a buffer to hold the value. DWORD type, length; status = RegQueryValueExW( key, name, 0, &type, 0, &length ); if (status != NO_ERROR) { IASTracePrintf( "RegQueryValueExW for %S failed with error %ld.", name, status ); break; } BYTE* data = static_cast(_alloca(length)); // Read the registry value. status = RegQueryValueExW( key, name, 0, &type, data, &length ); if (status != NO_ERROR) { IASTracePrintf( "RegQueryValueExW for %S failed with error %ld.", name, status ); break; } // Make sure it's the right type. if (type != REG_MULTI_SZ) { IASTracePrintf( "%S registry value is not of type REG_MULTI_SZ.", name ); status = ERROR_INVALID_DATA; break; } // Count the number of strings. size_t numExtensions = 0; const wchar_t* path; for (path = reinterpret_cast(data); *path != L'\0'; path += (wcslen(path) + 1)) { if (!IsNT4Only(path)) { ++numExtensions; } } // If there are no extensions, then we're done. if (numExtensions == 0) { IASTraceString("No extensions registered."); break; } // Allocate memory to hold the extensions. begin = new (std::nothrow) RadiusExtension[numExtensions]; if (begin == 0) { status = ERROR_NOT_ENOUGH_MEMORY; break; } // Load the DLL's. end = begin; for (path = reinterpret_cast(data); *path != L'\0'; path += (wcslen(path) + 1)) { if (!IsNT4Only(path)) { status = end->Load(path); if (status != NO_ERROR) { ignoreFindNotFound = false; // Clear any partial result. Clear(); break; } ++end; } } } while (false); // Close the registry. if (key != 0) { RegCloseKey(key); } // If no extensions are registered, then it's not really an error. if (ignoreFindNotFound && (status == ERROR_FILE_NOT_FOUND)) { status = NO_ERROR; } return status; } void RadiusExtensionPoint::Process( RADIUS_EXTENSION_CONTROL_BLOCK* ecb ) const throw () { IASTracePrintf("Invoking %S", name); for (const RadiusExtension* i = begin; i != end; ++i) { DWORD result = i->Process(ecb); if (result != NO_ERROR) { ecb->SetResponseType(ecb, rcDiscard); } } } void RadiusExtensionPoint::Clear() throw () { delete[] begin; begin = 0; end = 0; } bool RadiusExtensionPoint::IsNT4Only(const wchar_t* path) throw () { // Is this the authsam extension? return _wcsicmp(ExtractFileNameFromPath(path), L"AUTHSAM.DLL") == 0; }