/*******************************************************************/ /* Copyright(c) 1992 Microsoft Corporation */ /*******************************************************************/ //*** // // Filename: ppphand.c // // Description: This module contains the procedures for the // supervisor's procedure-driven state machine // that handle PPP events. // // Author: Stefan Solomon (stefans) May 26, 1992. // //*** #include "ddm.h" #include "timer.h" #include "handlers.h" #include "objects.h" #include "util.h" #include "routerif.h" #include #include #include #include #include "rasmanif.h" #include #include #include // // This lives in rasapi32.dll // DWORD DDMGetPppParameters( LPWSTR lpwsPhonebookName, LPWSTR lpwsPhonebookEntry, CHAR * szzPppParameters ); //*** // // Function: SvPppSendInterfaceInfo // // Description: Ppp engine wants to get the interface handles for this // connection. // VOID SvPppSendInterfaceInfo( IN PDEVICE_OBJECT pDeviceObj ) { ROUTER_INTERFACE_OBJECT * pIfObject; PPP_INTERFACE_INFO PppInterfaceInfo; DWORD dwXportIndex; PCONNECTION_OBJECT pConnObj; DDM_PRINT(gblDDMConfigInfo.dwTraceId, TRACE_FSM, "SvPppSendInterfaceHandles: Entered, hPort=%d",pDeviceObj->hPort); ZeroMemory( &PppInterfaceInfo, sizeof( PppInterfaceInfo ) ); if ( ( pConnObj = ConnObjGetPointer( pDeviceObj->hConnection ) ) == NULL ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "No ConnObj" ); return; } EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) ); if ( ( pIfObject = IfObjectGetPointer( pConnObj->hDIMInterface ) ) == NULL ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "No IfObject" ); LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) ); return; } // // Get handles to this interface for each transport and notify PPP. // for ( dwXportIndex = 0; dwXportIndex < gblDDMConfigInfo.dwNumRouterManagers; dwXportIndex++ ) { switch( gblRouterManagers[dwXportIndex].DdmRouterIf.dwProtocolId ) { case PID_IPX: if (pIfObject->Transport[dwXportIndex].fState & RITRANSPORT_ENABLED) { PppInterfaceInfo.hIPXInterface = pIfObject->Transport[dwXportIndex].hInterface; } else { PppInterfaceInfo.hIPXInterface = INVALID_HANDLE_VALUE; } break; case PID_IP: if (pIfObject->Transport[dwXportIndex].fState & RITRANSPORT_ENABLED) { PppInterfaceInfo.hIPInterface = pIfObject->Transport[dwXportIndex].hInterface; CopyMemory( PppInterfaceInfo.szzParameters, pIfObject->PppInterfaceInfo.szzParameters, sizeof( PppInterfaceInfo.szzParameters ) ); } else { PppInterfaceInfo.hIPInterface = INVALID_HANDLE_VALUE; } break; default: break; } } PppInterfaceInfo.IfType = pIfObject->IfType; LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) ); PppDdmSendInterfaceInfo( pDeviceObj->hConnection, &PppInterfaceInfo ); } //*** // // Function: SvPppUserOK // // Description: User has passed security verification and entered the // configuration conversation phase. Stops auth timer and // logs the user. // //*** VOID SvPppUserOK( IN PDEVICE_OBJECT pDeviceObj, IN PPPDDM_AUTH_RESULT * pAuthResult ) { LPWSTR lpstrAudit[2]; ROUTER_INTERFACE_OBJECT * pIfObject; PCONNECTION_OBJECT pConnObj; DWORD dwRetCode = NO_ERROR; WCHAR wchUserName[UNLEN+1]; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "SvPppUserOK: Entered, hPort=%d", pDeviceObj->hPort); if ( pDeviceObj->DeviceState != DEV_OBJ_AUTH_IS_ACTIVE ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "Auth not started" ); return; } // // Stop authentication timer // TimerQRemove( (HANDLE)pDeviceObj->hPort, SvAuthTimeout ); if ( strlen( pAuthResult->szUserName ) > 0 ) { MultiByteToWideChar( CP_ACP, 0, pAuthResult->szUserName, -1, wchUserName, UNLEN+1 ); } else { wcscpy( wchUserName, gblpszUnknown ); } // // Check to see if the username and domain are the same if the 3rd party // security DLL is installed.. // if ( ( gblDDMConfigInfo.lpfnRasBeginSecurityDialog != NULL ) && ( gblDDMConfigInfo.lpfnRasEndSecurityDialog != NULL ) && ( pDeviceObj->fFlags & DEV_OBJ_SECURITY_DLL_USED ) ) { // // If there is no match then hangup the line // if ( _wcsicmp( pDeviceObj->wchUserName, wchUserName ) != 0 ) { lpstrAudit[0] = pDeviceObj->wchUserName; lpstrAudit[1] = wchUserName; DDMLogWarning( ROUTERLOG_AUTH_DIFFUSER_FAILURE, 2, lpstrAudit ); PppDdmStop( pDeviceObj->hPort, ERROR_ACCESS_DENIED ); return; } } // // copy the user name // wcscpy( pDeviceObj->wchUserName, wchUserName ); // // copy the domain name // MultiByteToWideChar( CP_ACP, 0, pAuthResult->szLogonDomain, -1, pDeviceObj->wchDomainName, DNLEN+1 ); // // copy the advanced server flag // if ( pAuthResult->fAdvancedServer ) { pDeviceObj->fFlags |= DEV_OBJ_IS_ADVANCED_SERVER; } EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) ); do { // // Check to see if there are any non-client intefaces with this // name. // pIfObject = IfObjectGetPointerByName( pDeviceObj->wchUserName, FALSE ); if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL ) { // // If this is a client dialing in and clients are not allowed // to dialin to this port, then disconnect them. // if ( !( pDeviceObj->fFlags & DEV_OBJ_ALLOW_CLIENTS ) ) { dwRetCode = ERROR_NOT_CLIENT_PORT; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "A client tried to connect on a router only port=%d", pDeviceObj->hPort); break; } } else { // // If a call came in for an interface that is not dynamic // then do not accept the line // if ( ( pIfObject->IfType == ROUTER_IF_TYPE_DEDICATED ) || ( pIfObject->IfType == ROUTER_IF_TYPE_INTERNAL ) ) { // // Notify PPP not to accept the connection // dwRetCode = ERROR_ALREADY_CONNECTED; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "The interface %ws is already connected port=%d", pIfObject->lpwsInterfaceName, pDeviceObj->hPort ); break; } // // Allow the connection only if the interface is enabled // if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) ) { dwRetCode = ERROR_INTERFACE_DISABLED; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "The interface %ws is disabled", pIfObject->lpwsInterfaceName ); break; } if ( !( pDeviceObj->fFlags & DEV_OBJ_ALLOW_ROUTERS ) ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "A router tried to connect on a client only port=%d", pDeviceObj->hPort); dwRetCode = ERROR_NOT_ROUTER_PORT; break; } // // Set current usage in rasman to ROUTER // RasSetRouterUsage( pDeviceObj->hPort, TRUE ); } } while( FALSE ); LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) ); if ( dwRetCode != NO_ERROR ) { lpstrAudit[0] = pDeviceObj->wchUserName; lpstrAudit[1] = pDeviceObj->wchPortName; DDMLogWarningString( ROUTERLOG_CONNECTION_ATTEMPT_FAILURE, 2, lpstrAudit, dwRetCode, 2 ); PppDdmStop( pDeviceObj->hPort, dwRetCode ); } return; } //*** // // Function: SvPppNewLinkOrBundle // // Description: User has passed security verification and entered the // configuration conversation phase. Stops auth timer and // logs the user. // //*** VOID SvPppNewLinkOrBundle( IN PDEVICE_OBJECT pDeviceObj, IN BOOL fNewBundle, IN PBYTE pClientInterface, IN PBYTE pQuarantineIPFilter, IN PBYTE pFilter, IN BOOL fQuarantinePresent ) { LPWSTR lpstrAudit[2]; ROUTER_INTERFACE_OBJECT * pIfObject; PCONNECTION_OBJECT pConnObj; DWORD dwRetCode = NO_ERROR; WCHAR wchUserName[UNLEN+1]; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "SvPppNewLinkOrBundle: Entered, hPort=%d", pDeviceObj->hPort); if ( pDeviceObj->DeviceState != DEV_OBJ_AUTH_IS_ACTIVE ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "Auth not started" ); return; } // // Get handle to the connection or bundle for this link // if ( ( dwRetCode = RasPortGetBundle( NULL, pDeviceObj->hPort, &(pDeviceObj->hConnection) ) ) != NO_ERROR ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "RasPortGetBundle failed: %d", dwRetCode ); PppDdmStop( pDeviceObj->hPort, dwRetCode ); return; } // // Allocate a connection object if it does not exist yet // pConnObj = ConnObjGetPointer( pDeviceObj->hConnection ); if ( pConnObj == (CONNECTION_OBJECT *)NULL ) { pConnObj = ConnObjAllocateAndInit( INVALID_HANDLE_VALUE, pDeviceObj->hConnection ); if ( pConnObj == (CONNECTION_OBJECT *)NULL ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "ConnObjAllocateAndInit failed" ); PppDdmStop( pDeviceObj->hPort, ERROR_NOT_ENOUGH_MEMORY ); return; } pConnObj->fFlags = CONN_OBJ_IS_PPP; pConnObj->hPort = pDeviceObj->hPort; pConnObj->pQuarantineFilter = pQuarantineIPFilter; pConnObj->pFilter = pFilter; wcscpy( pConnObj->wchInterfaceName, pDeviceObj->wchUserName ); // // copy the user name // wcscpy( pConnObj->wchUserName, pDeviceObj->wchUserName ); // // copy the domain name // wcscpy( pConnObj->wchDomainName, pDeviceObj->wchDomainName ); // // If it is a router, check to see if we have an interface for this // router, otherwise reject this connection. // EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) ); do { // // Check to see if there are any non-client intefaces with this // name. // pIfObject = IfObjectGetPointerByName( pConnObj->wchInterfaceName, FALSE ); // // We do not have this interface in our database so assume that // this is a client so we need to create and interface and add it // to all the router managers. Also if this interface exists but // is for a client we need to add this interface again. // if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL ) { pIfObject = IfObjectAllocateAndInit( pConnObj->wchUserName, RISTATE_CONNECTING, ROUTER_IF_TYPE_CLIENT, pConnObj->hConnection, TRUE, 0, 0, NULL, NULL); if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL ) { // // Error log this and stop the connection. // dwRetCode = GetLastError(); DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "IfObjectAllocateAndInit failed: %d", dwRetCode); break; } // // Add interfaces to router managers, insert in table now // because of the table lookup within the InterfaceEnabled // call made in the context of AddInterface. // dwRetCode = IfObjectInsertInTable( pIfObject ); if ( dwRetCode != NO_ERROR ) { LOCAL_FREE( pIfObject ); DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "IfObjectInsertInTable failed: %d", dwRetCode ); break; } dwRetCode = IfObjectAddClientInterface( pIfObject, pClientInterface ); if ( dwRetCode != NO_ERROR ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "IfObjectAddClientInterface failed: %d", dwRetCode ); IfObjectRemove( pIfObject->hDIMInterface ); break; } if(fQuarantinePresent) { pConnObj->fFlags |= CONN_OBJ_QUARANTINE_PRESENT; } } else { // // If the interface is already connecting or connected // and this is a new bundle then we need to reject this // connection. // if ( pIfObject->State != RISTATE_DISCONNECTED ) { // // Notify PPP not to accept the connection // dwRetCode = ERROR_ALREADY_CONNECTED; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "The interface %ws is already connected port=%d", pIfObject->lpwsInterfaceName, pDeviceObj->hPort ); break; } } ConnObjInsertInTable( pConnObj ); pIfObject->State = RISTATE_CONNECTING; pConnObj->hDIMInterface = pIfObject->hDIMInterface; pConnObj->InterfaceType = pIfObject->IfType; } while( FALSE ); LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) ); if ( dwRetCode != NO_ERROR ) { PppDdmStop( pDeviceObj->hPort, dwRetCode ); LOCAL_FREE( pConnObj ); return; } } // // Since this is a new bundle also send the interface handles // if ( fNewBundle ) { SvPppSendInterfaceInfo( pDeviceObj ); } // // Add this link to the connection block. // if ( ( dwRetCode = ConnObjAddLink( pConnObj, pDeviceObj ) ) != NO_ERROR ) { PppDdmStop( pDeviceObj->hPort, ERROR_NOT_ENOUGH_MEMORY ); DDMLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode ); return; } } //*** // // Function: SvPppFailure // // Descr: Ppp will let us know of any failure while active on a port. // An error message is sent to us and we merely log it and // disconnect the port. // //*** VOID SvPppFailure( IN PDEVICE_OBJECT pDeviceObj, IN PPPDDM_FAILURE *afp ) { LPWSTR auditstrp[3]; WCHAR wchErrorString[256+1]; WCHAR wchUserName[UNLEN+DNLEN+1]; WCHAR wchDomainName[DNLEN+1]; DWORD dwRetCode; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "SvPppFailure: Entered, hPort=%d, Error=%d", pDeviceObj->hPort, afp->dwError ); // // Was this a failure for a BAP callback? // if ( pDeviceObj->fFlags & DEV_OBJ_BAP_CALLBACK ) { PppDdmBapCallbackResult( pDeviceObj->hBapConnection, afp->dwError ); pDeviceObj->fFlags &= ~DEV_OBJ_BAP_CALLBACK; } if ( afp->szUserName[0] != (CHAR)NULL ) { MultiByteToWideChar( CP_ACP, 0, afp->szUserName, -1, wchUserName, UNLEN+1 ); } else { wcscpy( wchUserName, gblpszUnknown ); } // // We ignore the DeviceState here because a Ppp failure can occur at // any time during the connection. // switch( afp->dwError ) { case ERROR_AUTHENTICATION_FAILURE: auditstrp[0] = wchUserName; auditstrp[1] = pDeviceObj->wchPortName; DDMLogWarning( ROUTERLOG_AUTH_FAILURE,2,auditstrp ); break; case ERROR_PASSWD_EXPIRED: MultiByteToWideChar( CP_ACP, 0, afp->szLogonDomain, -1, wchDomainName, DNLEN+1 ); auditstrp[0] = wchDomainName; auditstrp[1] = wchUserName; auditstrp[2] = pDeviceObj->wchPortName; DDMLogWarning( ROUTERLOG_PASSWORD_EXPIRED, 3, auditstrp ); break; case ERROR_ACCT_EXPIRED: case ERROR_ACCOUNT_EXPIRED: MultiByteToWideChar( CP_ACP, 0, afp->szLogonDomain, -1, wchDomainName, DNLEN+1 ); auditstrp[0] = wchDomainName; auditstrp[1] = wchUserName; auditstrp[2] = pDeviceObj->wchPortName; DDMLogWarning( ROUTERLOG_ACCT_EXPIRED, 3, auditstrp ); break; case ERROR_NO_DIALIN_PERMISSION: MultiByteToWideChar( CP_ACP, 0, afp->szLogonDomain, -1, wchDomainName, DNLEN+1 ); auditstrp[0] = wchDomainName; auditstrp[1] = wchUserName; auditstrp[2] = pDeviceObj->wchPortName; DDMLogWarning( ROUTERLOG_NO_DIALIN_PRIVILEGE, 3, auditstrp ); break; case ERROR_REQ_NOT_ACCEP: auditstrp[0] = pDeviceObj->wchPortName; DDMLogWarning( ROUTERLOG_LICENSE_LIMIT_EXCEEDED, 1, auditstrp ); break; case ERROR_BAP_DISCONNECTED: case ERROR_BAP_REQUIRED: auditstrp[0] = wchUserName; auditstrp[1] = pDeviceObj->wchPortName; DDMLogWarningString( ROUTERLOG_BAP_DISCONNECT, 2, auditstrp, afp->dwError, 2 ); break; case ERROR_PORT_NOT_CONNECTED: case ERROR_PPP_TIMEOUT: case ERROR_PPP_LCP_TERMINATED: case ERROR_NOT_CONNECTED: // // Ignore this error // break; case ERROR_PPP_NOT_CONVERGING: default: if ( afp->szUserName[0] != (CHAR)NULL ) { if ( afp->szLogonDomain[0] != (CHAR)NULL ) { MultiByteToWideChar(CP_ACP,0,afp->szLogonDomain,-1,wchUserName,UNLEN+1); wcscat( wchUserName, L"\\" ); MultiByteToWideChar(CP_ACP,0,afp->szUserName,-1,wchDomainName,DNLEN+1); wcscat( wchUserName, wchDomainName ); } else { MultiByteToWideChar(CP_ACP,0,afp->szUserName,-1,wchUserName,UNLEN+1); } } else if ( pDeviceObj->wchUserName[0] != (WCHAR)NULL ) { if ( pDeviceObj->wchDomainName[0] != (WCHAR)NULL ) { wcscpy( wchUserName, pDeviceObj->wchDomainName ); wcscat( wchUserName, L"\\" ); wcscat( wchUserName, pDeviceObj->wchUserName ); } else { wcscpy( wchUserName, pDeviceObj->wchUserName ); } } else { wcscpy( wchUserName, gblpszUnknown ); } auditstrp[0] = pDeviceObj->wchPortName; auditstrp[1] = wchUserName; DDMLogErrorString(ROUTERLOG_PPP_FAILURE, 2, auditstrp, afp->dwError, 2); break; } } //*** // // Function: SvPppCallbackRequest // // Description: // //*** VOID SvPppCallbackRequest( IN PDEVICE_OBJECT pDeviceObj, IN PPPDDM_CALLBACK_REQUEST *cbrp ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "SvPppCallbackRequest: Entered, hPort = %d\n",pDeviceObj->hPort); // // check the state // if (pDeviceObj->DeviceState != DEV_OBJ_AUTH_IS_ACTIVE) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "Auth not started" ); return; } TimerQRemove( (HANDLE)pDeviceObj->hPort, SvAuthTimeout ); // // copy relevant fields in our dcb // if (cbrp->fUseCallbackDelay) { pDeviceObj->dwCallbackDelay = cbrp->dwCallbackDelay; } else { pDeviceObj->dwCallbackDelay = gblDDMConfigInfo.dwCallbackTime; } MultiByteToWideChar( CP_ACP, 0, cbrp->szCallbackNumber, -1, pDeviceObj->wchCallbackNumber, MAX_PHONE_NUMBER_LEN + 1 ); // // Disconnect the line and change the state // pDeviceObj->DeviceState = DEV_OBJ_CALLBACK_DISCONNECTING; // // Wait to enable the client to get the message // TimerQRemove( (HANDLE)pDeviceObj->hPort, SvDiscTimeout ); TimerQInsert( (HANDLE)pDeviceObj->hPort, DISC_TIMEOUT_CALLBACK, SvDiscTimeout ); } //*** // // Function: SvPppDone // // Description: Activates all allocated bindings. // //*** VOID SvPppDone( IN PDEVICE_OBJECT pDeviceObj, IN PPP_PROJECTION_RESULT *pProjectionResult ) { LPWSTR lpstrAudit[3]; DWORD dwRetCode; DWORD dwNumActivatedProjections = 0; ROUTER_INTERFACE_OBJECT * pIfObject; CONNECTION_OBJECT * pConnObj; WCHAR wchFullUserName[UNLEN+DNLEN+2]; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "SvPppDone: Entered, hPort=%d", pDeviceObj->hPort); // // If we are not authenicating and not been authenticated then we ignore // this message. // if ( ( pDeviceObj->DeviceState != DEV_OBJ_AUTH_IS_ACTIVE ) && ( pDeviceObj->DeviceState != DEV_OBJ_ACTIVE ) ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "We are not authenicating and not been authenticated" ); return; } // // Get pointer to connection object. If we cannot find it that means we // have gotten a PPP message for a device who's connection does not exist. // Simply ignore it. // if ( ( pConnObj = ConnObjGetPointer( pDeviceObj->hConnection ) ) == NULL ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "No ConnObj" ); return; } // // If we are getting a projection info structure again, we just update it // and return. // if ( pDeviceObj->DeviceState == DEV_OBJ_ACTIVE ) { pConnObj->PppProjectionResult = *pProjectionResult; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "Updated projection info structure" ); return; } if ( pConnObj->wchDomainName[0] != TEXT('\0') ) { wcscpy( wchFullUserName, pConnObj->wchDomainName ); wcscat( wchFullUserName, TEXT("\\") ); wcscat( wchFullUserName, pConnObj->wchUserName ); } else { wcscpy( wchFullUserName, pConnObj->wchUserName ); } lpstrAudit[0] = wchFullUserName; lpstrAudit[1] = pDeviceObj->wchPortName; // // If we have not yet been notifyied of projections for this connection. // if ( !(pConnObj->fFlags & CONN_OBJ_PROJECTIONS_NOTIFIED) ) { if ( pProjectionResult->ip.dwError == NO_ERROR ) { dwNumActivatedProjections++; } if ( pProjectionResult->ipx.dwError == NO_ERROR ) { dwNumActivatedProjections++; } if ( pProjectionResult->at.dwError == NO_ERROR ) { dwNumActivatedProjections++; } // // We couldn't activate any projection due to some error error log // and bring the link down // if ( dwNumActivatedProjections == 0 ) { DDMLogError(ROUTERLOG_AUTH_NO_PROJECTIONS, 2, lpstrAudit, NO_ERROR); PppDdmStop( pDeviceObj->hPort, NO_ERROR ); return; } else { // // Even though NBF was removed from the product, we can // still get the computer namefrom the nbf projection result // (PPP Engine dummied it in there). // // If the computer name ends with 0x03, that tells us // the messenger service is running on the remote computer. // pConnObj->fFlags &= ~CONN_OBJ_MESSENGER_PRESENT; pConnObj->bComputerName[0] = (CHAR)NULL; if ( pProjectionResult->nbf.wszWksta[0] != (WCHAR)NULL ) { WideCharToMultiByte( CP_ACP, 0, pProjectionResult->nbf.wszWksta, -1, pConnObj->bComputerName, sizeof( pConnObj->bComputerName ), NULL, NULL ); if (pConnObj->bComputerName[NCBNAMSZ-1] == (WCHAR) 0x03) { pConnObj->fFlags |= CONN_OBJ_MESSENGER_PRESENT; } pConnObj->bComputerName[NCBNAMSZ-1] = (WCHAR)NULL; } } // // Projections Activated OK // pConnObj->PppProjectionResult = *pProjectionResult; pConnObj->fFlags |= CONN_OBJ_PROJECTIONS_NOTIFIED; // // Set this interface to connected if it is not already connected // dwRetCode = IfObjectConnected( pConnObj->hDIMInterface, pConnObj->hConnection, &(pConnObj->PppProjectionResult) ); // // If the interface does not exist anymore bring down this connection // if ( dwRetCode != NO_ERROR ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "Interface does not exist anymore" ); PppDdmStop( pDeviceObj->hPort, NO_ERROR ); ConnObjDisconnect( pConnObj ); return; } GetSystemTimeAsFileTime( (FILETIME*)&(pConnObj->qwActiveTime) ); if ( !AcceptNewConnection( pDeviceObj, pConnObj ) ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "ERROR_ACCESS_DENIED" ); PppDdmStop( pDeviceObj->hPort, ERROR_ACCESS_DENIED ); ConnObjDisconnect( pConnObj ); return; } } if ( !AcceptNewLink( pDeviceObj, pConnObj ) ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "ERROR_ACCESS_DENIED" ); PppDdmStop( pDeviceObj->hPort, ERROR_ACCESS_DENIED ); return; } // // Reduce the media count for this device // if ( !(pDeviceObj->fFlags & DEV_OBJ_MARKED_AS_INUSE) ) { if ( pDeviceObj->fFlags & DEV_OBJ_ALLOW_ROUTERS ) { MediaObjRemoveFromTable( pDeviceObj->wchDeviceType ); } pDeviceObj->fFlags |= DEV_OBJ_MARKED_AS_INUSE; gblDeviceTable.NumDevicesInUse++; // // Possibly need to notify the router managers of unreachability // EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) ); IfObjectNotifyAllOfReachabilityChange( FALSE, INTERFACE_OUT_OF_RESOURCES ); LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) ); } // // log authentication success, 18 is MSPPC // if ( ( pConnObj->PppProjectionResult.ccp.dwSendProtocol == 18 ) && ( pConnObj->PppProjectionResult.ccp.dwReceiveProtocol == 18 ) ) { if ( ( pConnObj->PppProjectionResult.ccp.dwReceiveProtocolData & ( MSTYPE_ENCRYPTION_40 | MSTYPE_ENCRYPTION_40F | MSTYPE_ENCRYPTION_56 | MSTYPE_ENCRYPTION_128 ) ) && ( pConnObj->PppProjectionResult.ccp.dwSendProtocolData & ( MSTYPE_ENCRYPTION_40 | MSTYPE_ENCRYPTION_40F | MSTYPE_ENCRYPTION_56 | MSTYPE_ENCRYPTION_128 ) ) ) { if ( ( pConnObj->PppProjectionResult.ccp.dwSendProtocolData & MSTYPE_ENCRYPTION_128 ) && ( pConnObj->PppProjectionResult.ccp.dwReceiveProtocolData & MSTYPE_ENCRYPTION_128 ) ) { DDMLogInformation(ROUTERLOG_AUTH_SUCCESS_STRONG_ENCRYPTION,2, lpstrAudit); } else { DDMLogInformation(ROUTERLOG_AUTH_SUCCESS_ENCRYPTION,2, lpstrAudit); } } else { DDMLogInformation( ROUTERLOG_AUTH_SUCCESS, 2, lpstrAudit ); } if(pProjectionResult->ip.dwError == ERROR_SUCCESS) { WCHAR *pszIpAddress = GetIpAddress(pProjectionResult->ip.dwRemoteAddress); if(NULL != pszIpAddress) { lpstrAudit[2] = pszIpAddress; DDMLogInformation(ROUTERLOG_IP_USER_CONNECTED, 3, lpstrAudit); LocalFree(pszIpAddress); } } } else { DDMLogInformation( ROUTERLOG_AUTH_SUCCESS, 2, lpstrAudit ); if(pProjectionResult->ip.dwError == ERROR_SUCCESS) { WCHAR *pszIpAddress = GetIpAddress( pProjectionResult->ip.dwRemoteAddress); if(NULL != pszIpAddress) { lpstrAudit[2] = pszIpAddress; DDMLogInformation(ROUTERLOG_IP_USER_CONNECTED, 3, lpstrAudit); LocalFree(pszIpAddress); } } } // // and finaly go to ACTIVE state // pDeviceObj->DeviceState = DEV_OBJ_ACTIVE; pDeviceObj->dwTotalNumberOfCalls++; pDeviceObj->fFlags |= DEV_OBJ_PPP_IS_ACTIVE; // // and initialize the active time // GetSystemTimeAsFileTime( (FILETIME*)&(pDeviceObj->qwActiveTime) ); // // Was this a connection for a BAP callback? // if ( pDeviceObj->fFlags & DEV_OBJ_BAP_CALLBACK ) { PppDdmBapCallbackResult( pDeviceObj->hBapConnection, NO_ERROR ); pDeviceObj->fFlags &= ~DEV_OBJ_BAP_CALLBACK; } return; } //** // // Call: SvAddLinkToConnection // // Returns: NO_ERROR - Success // Non-zero returns - Failure // // Description: Called to actually add a new link that BAP has brought up. // VOID SvAddLinkToConnection( IN PDEVICE_OBJECT pDeviceObj, IN HRASCONN hRasConn ) { CONNECTION_OBJECT * pConnObj; DWORD dwRetCode; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "SvAddLinkToConnection: Entered, hPort=%d", pDeviceObj->hPort ); // // Set this port to be notified by rasapi32 on disconnect. // dwRetCode = RasConnectionNotification( hRasConn, gblSupervisorEvents[NUM_DDM_EVENTS + (gblDeviceTable.NumDeviceBuckets*2) + DeviceObjHashPortToBucket(pDeviceObj->hPort)], RASCN_Disconnection ); if ( dwRetCode != NO_ERROR ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "RasConnectionNotification failed: %d", dwRetCode ); return; } // // Get the HCONN bundle handle for this port // if ( RasPortGetBundle( NULL, pDeviceObj->hPort, &(pDeviceObj->hConnection) ) ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "RasPortGetBundle failed" ); return; } if ( ( pConnObj = ConnObjGetPointer( pDeviceObj->hConnection ) ) == NULL ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "No ConnObj" ); return; } if ( ( dwRetCode = ConnObjAddLink( pConnObj, pDeviceObj ) ) != NO_ERROR ) { DDMLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode ); return; } // // Reduce the media count for this device // if ( !(pDeviceObj->fFlags & DEV_OBJ_MARKED_AS_INUSE) ) { if ( pDeviceObj->fFlags & DEV_OBJ_ALLOW_ROUTERS ) { MediaObjRemoveFromTable( pDeviceObj->wchDeviceType ); } pDeviceObj->fFlags |= DEV_OBJ_MARKED_AS_INUSE; gblDeviceTable.NumDevicesInUse++; // // Possibly need to notify the router managers of unreachability // IfObjectNotifyAllOfReachabilityChange(FALSE,INTERFACE_OUT_OF_RESOURCES); } pDeviceObj->fFlags |= DEV_OBJ_OPENED_FOR_DIALOUT; pDeviceObj->hRasConn = hRasConn; if ( pConnObj->InterfaceType == ROUTER_IF_TYPE_FULL_ROUTER ) { RasSetRouterUsage( pDeviceObj->hPort, TRUE ); } } //** // // Call: SvDoBapCallbackRequest // // Returns: NO_ERROR - Success // Non-zero returns - Failure // // Description: Called by BAP to initiate a callback to the remote peer // VOID SvDoBapCallbackRequest( IN PDEVICE_OBJECT pDevObj, IN HCONN hConnection, IN CHAR * szCallbackNumber ) { DWORD dwRetCode; DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "SvDoBapCallbackRequest: Entered, hPort=%d", pDevObj->hPort ); // // Check to see if the device is available // if ( ( pDevObj->DeviceState != DEV_OBJ_LISTENING ) || ( pDevObj->fFlags & DEV_OBJ_OPENED_FOR_DIALOUT ) ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "Device not available" ); PppDdmBapCallbackResult( hConnection, ERROR_PORT_NOT_AVAILABLE ); return; } pDevObj->fFlags |= DEV_OBJ_IS_PPP; pDevObj->DeviceState = DEV_OBJ_CALLBACK_DISCONNECTING; MultiByteToWideChar( CP_ACP, 0, szCallbackNumber, -1, pDevObj->wchCallbackNumber, MAX_PHONE_NUMBER_LEN + 1 ); pDevObj->dwCallbackDelay = 10; pDevObj->hBapConnection = hConnection; pDevObj->fFlags |= DEV_OBJ_BAP_CALLBACK; RmDisconnect( pDevObj ); } //*** // // Function: PppEventHandler // // Description: receives the ppp messages and invokes the apropriate // procedures in fsm. // //*** VOID PppEventHandler( VOID ) { PPP_MESSAGE PppMsg; PDEVICE_OBJECT pDevObj; PCONNECTION_OBJECT pConnObj; // // loop to get all messages // while( ServerReceiveMessage( MESSAGEQ_ID_PPP, (BYTE *)&PppMsg) ) { EnterCriticalSection( &(gblDeviceTable.CriticalSection) ); if ( PppMsg.dwMsgId == PPPDDMMSG_PnPNotification ) { // // Port add/removal/change usage or protocol addition/removal // notifications. // DWORD dwPnPEvent = PppMsg.ExtraInfo.DdmPnPNotification.PnPNotification.dwEvent; RASMAN_PORT * pRasmanPort = &(PppMsg.ExtraInfo.DdmPnPNotification.PnPNotification.RasPort); switch( dwPnPEvent ) { case PNPNOTIFEVENT_CREATE: if(pRasmanPort->P_ConfiguredUsage & (CALL_IN | CALL_ROUTER | CALL_OUTBOUND_ROUTER)) { DeviceObjAdd( pRasmanPort ); } break; case PNPNOTIFEVENT_REMOVE: DeviceObjRemove( pRasmanPort ); break; case PNPNOTIFEVENT_USAGE: DeviceObjUsageChange( pRasmanPort ); break; } LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); continue; } else { // // Otherwise identify the port for which this event is received. // if ( ( pDevObj = DeviceObjGetPointer( PppMsg.hPort ) ) == NULL ) { RTASSERT( pDevObj != NULL ); LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); continue; } } // // action on the message type // switch( PppMsg.dwMsgId ) { case PPPDDMMSG_BapCallbackRequest: SvDoBapCallbackRequest( pDevObj, PppMsg.ExtraInfo.BapCallbackRequest.hConnection, PppMsg.ExtraInfo.BapCallbackRequest.szCallbackNumber ); break; case PPPDDMMSG_PppDone: pDevObj->fFlags &= (~DEV_OBJ_AUTH_ACTIVE); SvPppDone(pDevObj, &PppMsg.ExtraInfo.ProjectionResult); break; case PPPDDMMSG_CallbackRequest: SvPppCallbackRequest(pDevObj,&PppMsg.ExtraInfo.CallbackRequest); break; case PPPDDMMSG_Authenticated: SvPppUserOK(pDevObj, &PppMsg.ExtraInfo.AuthResult); break; case PPPDDMMSG_NewLink: SvPppNewLinkOrBundle( pDevObj, FALSE, NULL, NULL, NULL, FALSE ); break; case PPPDDMMSG_NewBundle: if(NULL != IfObjectGetPointerByName( pDevObj->wchUserName, FALSE)) { MprInfoDelete(PppMsg.ExtraInfo.DdmNewBundle.pClientInterface); PppMsg.ExtraInfo.DdmNewBundle.pClientInterface = NULL; MprInfoDelete(PppMsg.ExtraInfo.DdmNewBundle.pQuarantineIPFilter); PppMsg.ExtraInfo.DdmNewBundle.pQuarantineIPFilter = NULL; MprInfoDelete(PppMsg.ExtraInfo.DdmNewBundle.pFilter); PppMsg.ExtraInfo.DdmNewBundle.pFilter = NULL; PppMsg.ExtraInfo.DdmNewBundle.fQuarantinePresent = FALSE; } SvPppNewLinkOrBundle( pDevObj, TRUE, PppMsg.ExtraInfo.DdmNewBundle.pClientInterface, PppMsg.ExtraInfo.DdmNewBundle.pQuarantineIPFilter, PppMsg.ExtraInfo.DdmNewBundle.pFilter, PppMsg.ExtraInfo.DdmNewBundle.fQuarantinePresent); if ( PppMsg.ExtraInfo.DdmNewBundle.pClientInterface != NULL ) { MprInfoDelete( PppMsg.ExtraInfo.DdmNewBundle.pClientInterface ); } break; case PPPDDMMSG_PppFailure: pDevObj->fFlags &= (~DEV_OBJ_AUTH_ACTIVE); switch( PppMsg.ExtraInfo.DdmFailure.dwError ) { case NO_ERROR: case ERROR_IDLE_DISCONNECTED: pDevObj->dwDisconnectReason = DDM_IDLE_DISCONNECT; break; case ERROR_PPP_SESSION_TIMEOUT: pDevObj->dwDisconnectReason = DDM_SESSION_TIMEOUT; break; default: pDevObj->dwDisconnectReason = 0; SvPppFailure( pDevObj, &PppMsg.ExtraInfo.DdmFailure ); } PppDdmStop( pDevObj->hPort, PppMsg.ExtraInfo.DdmFailure.dwError ); break; case PPPDDMMSG_Stopped: if ( ( pDevObj->DeviceState != DEV_OBJ_CLOSING ) && ( pDevObj->DeviceState != DEV_OBJ_LISTENING ) ) { DevStartClosing( pDevObj ); } break; case PPPDDMMSG_PortCleanedUp: if ( pDevObj->DeviceState != DEV_OBJ_LISTENING ) { pDevObj->fFlags &= (~DEV_OBJ_PPP_IS_ACTIVE); if ( pDevObj->DeviceState != DEV_OBJ_CLOSING ) { DevStartClosing( pDevObj ); } else { DevCloseComplete( pDevObj ); } } break; case PPPDDMMSG_NewBapLinkUp: SvAddLinkToConnection( pDevObj, PppMsg.ExtraInfo.BapNewLinkUp.hRasConn ); break; default: RTASSERT(FALSE); break; } LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); } }