// Copyright (c) 1997, Microsoft Corporation, all rights reserved // // eapcfg.c // EAP package utility library // // These utility routines wrap the third-party EAP authentication // configuration information written to the registry by third-party EAP // security package providers. // // 11/25/97 Steve Cobb // #include #include #include #include #include #include // EAP configuration registry definitions. // #define REGKEY_Eap TEXT("System\\CurrentControlSet\\Services\\Rasman\\PPP\\EAP") #define REGVAL_szFriendlyName TEXT("FriendlyName") #define REGVAL_szConfigDll TEXT("ConfigUIPath") #define REGVAL_szIdentityDll TEXT("IdentityPath") #define REGVAL_fRequirePwd TEXT("InvokePasswordDialog") #define REGVAL_fRequireUser TEXT("InvokeUsernameDialog") #define REGVAL_pData TEXT("ConfigData") #define REGVAL_fForceConfig TEXT("RequireConfigUI") #define REGVAL_fMppeSupported TEXT("MPPEEncryptionSupported") // // HACKY Key not to display PEAP and Eapmschapv2 type in here // #define REGVAL_fHidePEAPMSChapv2 TEXT("HidePEAPMSChapv2") #define EAPTYPE_PEAP "25" #define EAPTYPE_EAPMSCHAPv2 "26" //----------------------------------------------------------------------------- // EAP configuration utilitiy routines (alphabetically) //----------------------------------------------------------------------------- DTLNODE* CreateEapcfgNode( void ) // Returns a created, empty EAPCFG descriptor node, or NULL on error. // { DTLNODE* pNode; EAPCFG* pEapcfg; pNode = DtlCreateSizedNode( sizeof(EAPCFG), 0L ); if (pNode) { pEapcfg = (EAPCFG* )DtlGetData( pNode ); ASSERT( pEapcfg ); pEapcfg->dwKey = (DWORD )-1; pEapcfg->pszConfigDll = NULL; pEapcfg->pszIdentityDll = NULL; pEapcfg->dwStdCredentialFlags = 0; pEapcfg->fProvidesMppeKeys = FALSE; pEapcfg->fForceConfig = FALSE; pEapcfg->pData = NULL; pEapcfg->cbData = 0; pEapcfg->fConfigDllCalled = FALSE; } return pNode; } VOID DestroyEapcfgNode( IN OUT DTLNODE* pNode ) // Release resources associated with EAPCFG node 'pNode'. See // DtlDestroyList. // { EAPCFG* pEapcfg; ASSERT( pNode ); pEapcfg = (EAPCFG* )DtlGetData( pNode ); ASSERT( pEapcfg ); Free0( pEapcfg->pszConfigDll ); Free0( pEapcfg->pszIdentityDll ); Free0( pEapcfg->pData ); DtlDestroyNode( pNode ); } DTLNODE* EapcfgNodeFromKey( IN DTLLIST* pList, IN DWORD dwKey ) // Returns the EAPCFG node in list 'pList' with EAP key value of 'dwKey' // or NULL if not found. // { DTLNODE* pNode; for (pNode = DtlGetFirstNode( pList ); pNode; pNode = DtlGetNextNode( pNode )) { EAPCFG* pEapcfg = (EAPCFG* )DtlGetData( pNode ); ASSERT( pEapcfg ); if (pEapcfg->dwKey == dwKey) { return pNode; } } return NULL; } // // Will tell us if there is a need to cripple PEAP // - if true is retured, we dont show PEAP and eapmschapv2 // in the list. BOOL IsRasDlgPeapCrippled(HKEY hkeyEap) { BOOL fRetCode = FALSE; DWORD dwRetCode = NO_ERROR; DWORD dwValue = 0; DWORD dwType = 0; DWORD cbValueDataSize = sizeof(DWORD); dwRetCode = RegQueryValueEx( hkeyEap, REGVAL_fHidePEAPMSChapv2, NULL, &dwType, (PBYTE)&dwValue, &cbValueDataSize ); if ( dwRetCode != NO_ERROR ) { goto LDone; } if ( dwValue != 0 ) { fRetCode = TRUE; } LDone: return fRetCode; } DTLLIST* ReadEapcfgList( IN TCHAR* pszMachine ) // Returns the address of a created list of installed custom // authentication packages or NULL if none could be read. On success, it // is caller's responsibility to eventually call DtlDestroyList on the // returned list. // { DWORD dwErr; BOOL fOk = FALSE; DTLLIST* pList; DTLNODE* pNode; EAPCFG* pEapcfg; HKEY hkeyLM = NULL; HKEY hkeyEap = NULL; HKEY hkeyPackage = NULL; CHAR szEapType[ 11 + 1 ]; TCHAR* psz; DWORD dw; DWORD cb; INT i; TCHAR* szCLSID; HRESULT hr; BOOL fRasDlgPeapCrippled = FALSE; pList = DtlCreateList( 0L ); if (!pList) { return NULL; } // Open the EAP key which contains a sub-key for each installed package. // dwErr = RegConnectRegistry( pszMachine, HKEY_LOCAL_MACHINE, &hkeyLM ); if (dwErr != 0 || !hkeyLM) { return pList; } dwErr = RegOpenKeyEx( hkeyLM, (LPCTSTR )REGKEY_Eap, 0, KEY_READ, &hkeyEap ); RegCloseKey( hkeyLM ); if (dwErr != 0) { return pList; } fRasDlgPeapCrippled = IsRasDlgPeapCrippled ( hkeyEap ); // Open each sub-key and extract the package definition from it's values. // Problems with opening individual sub-keys result in that node only // being discarded. // for (i = 0; TRUE; ++i) { cb = sizeof(szEapType); dwErr = RegEnumKeyExA( hkeyEap, i, szEapType, &cb, NULL, NULL, NULL, NULL ); if (dwErr != 0) { // Includes "out of items", the normal loop termination. // break; } dwErr = RegOpenKeyExA( hkeyEap, szEapType, 0, KEY_READ, &hkeyPackage ); if (dwErr != 0) { continue; } // For whistler bug 442519 and 442458 gangz // For LEAP, a RolesSupported DWORD will be added, if it is set to 2, // then we wont show it on the client side { DWORD dwRolesSupported = 0; GetRegDword( hkeyPackage, RAS_EAP_VALUENAME_ROLES_SUPPORTED, &dwRolesSupported); // This values is not configured, or equals 0 or 1, then go ahead // and show it, or else wont show it // 0 means can be either Authenticator or Authenticatee // 1 means can ONLY be Authenticator, for LEAP, it is 1 // 2 means can ONLY be Authenticatee if ( 0 != dwRolesSupported ) { if ( !(RAS_EAP_ROLE_AUTHENTICATEE & dwRolesSupported ) ) { continue; } if ( RAS_EAP_ROLE_EXCLUDE_IN_EAP & dwRolesSupported ) { continue; } if ( RAS_EAP_ROLE_EXCLUDE_IN_VPN & dwRolesSupported ) { continue; } } } do { pNode = CreateEapcfgNode(); if (!pNode) { break; } pEapcfg = (EAPCFG* )DtlGetData( pNode ); ASSERT( pEapcfg ); // EAP type ID. // pEapcfg->dwKey = (LONG )atol( szEapType ); // Friendly display name. // psz = NULL; dwErr = GetRegSz( hkeyPackage, REGVAL_szFriendlyName, &psz ); if (dwErr != 0) { break; } if (!*psz) { Free( psz ); psz = StrDupTFromA( szEapType ); if (!psz) { break; } } pEapcfg->pszFriendlyName = psz; // Configuration DLL path. // psz = NULL; dwErr = GetRegExpandSz( hkeyPackage, REGVAL_szConfigDll, &psz ); if (dwErr != 0) { break; } if (*psz) { pEapcfg->pszConfigDll = psz; } else { Free( psz ); } // Identity DLL path. // psz = NULL; dwErr = GetRegExpandSz( hkeyPackage, REGVAL_szIdentityDll, &psz ); if (dwErr != 0) { break; } if (*psz) { pEapcfg->pszIdentityDll = psz; } else { Free( psz ); } // Prompt user name // dw = 1; GetRegDword( hkeyPackage, REGVAL_fRequireUser, &dw ); if (dw) pEapcfg->dwStdCredentialFlags |= EAPCFG_FLAG_RequireUsername; // Prompt password // dw = 0; GetRegDword( hkeyPackage, REGVAL_fRequirePwd, &dw ); if (dw) pEapcfg->dwStdCredentialFlags |= EAPCFG_FLAG_RequirePassword; // MPPE encryption keys flag. // dw = 0; GetRegDword( hkeyPackage, REGVAL_fMppeSupported, &dw ); pEapcfg->fProvidesMppeKeys = !!dw; // Force configuration API to run at least once. // dw = FALSE; GetRegDword( hkeyPackage, REGVAL_fForceConfig, &dw ); pEapcfg->fForceConfig = !!dw; // Configuration blob. // GetRegBinary( hkeyPackage, REGVAL_pData, &pEapcfg->pData, &pEapcfg->cbData ); // ConfigCLSID // dwErr = GetRegSz( hkeyPackage, RAS_EAP_VALUENAME_CONFIG_CLSID, &szCLSID ); if (dwErr != 0) { break; } // Ignore errors. Eg. EAP MD5-Challenge does not have a ConfigCLSID. // hr = CLSIDFromString( szCLSID, &( pEapcfg->guidConfigCLSID ) ); Free( szCLSID ); // Add the completed node to the list. // DtlAddNodeLast( pList, pNode ); fOk = TRUE; } while (FALSE); if (!fOk && pNode) { DestroyEapcfgNode( pNode ); } RegCloseKey( hkeyPackage ); } RegCloseKey( hkeyEap ); return pList; }