#include "precomp.h" BOOL UserServerInfoIsInit( IN RASMON_SERVERINFO * pServerInfo) { return ((pServerInfo->hServer) || (pServerInfo->dwBuild == RASMONTR_OS_BUILD_NT40)); } DWORD UserServerInfoInit( IN RASMON_SERVERINFO * pServerInfo) { DWORD dwErr = NO_ERROR; BOOL bInit = UserServerInfoIsInit(pServerInfo); // If we're already initailized, return // if (bInit) { return NO_ERROR; } if ((pServerInfo->dwBuild != RASMONTR_OS_BUILD_NT40) && (pServerInfo->hServer == NULL)) { // // first time connecting to user server // MprAdminUserServerConnect ( pServerInfo->pszServer, TRUE, &(pServerInfo->hServer)); } return dwErr; } DWORD UserServerInfoUninit( IN RASMON_SERVERINFO * pServerInfo) { // Release the reference to the user server if (g_pServerInfo->hServer) { MprAdminUserServerDisconnect(g_pServerInfo->hServer); g_pServerInfo->hServer = NULL; } return NO_ERROR; } DWORD UserGetRasProperties ( IN RASMON_SERVERINFO * pServerInfo, IN LPCWSTR pwszUser, IN RAS_USER_0* pUser0) { HANDLE hUser = NULL; DWORD dwErr; BOOL bInit = UserServerInfoIsInit(pServerInfo); do { UserServerInfoInit(pServerInfo); // Get the information using nt40 apis // if (pServerInfo->dwBuild == RASMONTR_OS_BUILD_NT40) { dwErr = MprAdminUserGetInfo( pServerInfo->pszServer, pwszUser, 0, (LPBYTE)pUser0); if (dwErr != NO_ERROR) { break; } } // Or get it using nt50 apis else { // Get a reference to the given user // dwErr = MprAdminUserOpen( pServerInfo->hServer, (LPWSTR)pwszUser, &hUser); if (dwErr isnot NO_ERROR) { break; } // Set the information // dwErr = MprAdminUserRead( hUser, 1, // Gives us RASPRIV_DialinPolicy (LPBYTE)pUser0); if (dwErr isnot NO_ERROR) { break; } } } while (FALSE); // Cleanup // { if(hUser) { MprAdminUserClose(hUser); } if (!bInit) { UserServerInfoUninit(pServerInfo); } } return dwErr; } DWORD UserSetRasProperties ( IN RASMON_SERVERINFO * pServerInfo, IN LPCWSTR pwszUser, IN RAS_USER_0* pUser0) { HANDLE hUser = NULL; DWORD dwErr; BOOL bInit = UserServerInfoIsInit(pServerInfo); do { UserServerInfoInit(pServerInfo); // Set the information using nt40 apis // if (pServerInfo->dwBuild == RASMONTR_OS_BUILD_NT40) { dwErr = MprAdminUserSetInfo( pServerInfo->pszServer, pwszUser, 0, (LPBYTE)pUser0); if (dwErr != NO_ERROR) { break; } } // Or get it using nt50 apis else { // Get a reference to the given user // dwErr = MprAdminUserOpen( pServerInfo->hServer, (LPWSTR)pwszUser, &hUser); if (dwErr isnot NO_ERROR) { break; } // Set the information // dwErr = MprAdminUserWrite( hUser, 1, // Gives us RASPRIV_DialinPolicy (LPBYTE)pUser0); if (dwErr isnot NO_ERROR) { break; } } } while (FALSE); // Cleanup // { if(hUser) { MprAdminUserClose(hUser); } if (!bInit) { UserServerInfoUninit(pServerInfo); } } return dwErr; } DWORD UserAdd( IN LPCWSTR pwszServer, IN PRASUSER_DATA pUser) /*++ Routine Description: Adds the given user to the system --*/ { NET_API_STATUS nStatus; USER_INFO_2 * pUser2; LPCWSTR pwszFmtServer = pwszServer; // Initialize the base user information USER_INFO_1 UserInfo1 = { pUser->pszUsername, pUser->pszPassword, 0, USER_PRIV_USER, L"", L"", UF_SCRIPT | UF_DONT_EXPIRE_PASSWD | UF_NORMAL_ACCOUNT, L"" }; // Add the user nStatus = NetUserAdd( pwszFmtServer, 1, (LPBYTE)&UserInfo1, NULL); // If the user wasn't added, find out why if (nStatus != NERR_Success) { switch (nStatus) { case ERROR_ACCESS_DENIED: return ERROR_ACCESS_DENIED; case NERR_UserExists: return ERROR_USER_EXISTS; case NERR_PasswordTooShort: return ERROR_INVALID_PASSWORDNAME; } return ERROR_CAN_NOT_COMPLETE; } // Add the user's full name if provided if (pUser->pszFullname) { // add the user's full name nStatus = NetUserGetInfo( pwszFmtServer, pUser->pszUsername, 2, (LPBYTE*)&pUser2); if (nStatus is NERR_Success) { // Modify the full name in the structure pUser2->usri2_full_name = pUser->pszFullname; NetUserSetInfo( pwszFmtServer, pUser->pszUsername, 2, (LPBYTE)pUser2, NULL); NetApiBufferFree((LPBYTE)pUser2); return NO_ERROR; } return ERROR_CAN_NOT_COMPLETE; } return NO_ERROR; } DWORD UserDelete( IN LPCWSTR pwszServer, IN PRASUSER_DATA pUser) /*++ Routine Description: Deletes the given user from the system --*/ { NET_API_STATUS nStatus; // Delete the user and return the status code. If the // specified user is not in the user database, consider // it a success nStatus = NetUserDel( pwszServer, pUser->pszUsername); if (nStatus is NERR_UserNotFound) { return NO_ERROR; } return (nStatus is NERR_Success) ? NO_ERROR : ERROR_CAN_NOT_COMPLETE; } DWORD UserDumpConfig( IN HANDLE hFile ) /*++ Routine Description: Dumps a script to set the ras USER information to the given text file. Arguments: Return Value: NO_ERROR --*/ { DWORD dwErr; // Enumerate the users dumping them as we go dwErr = UserEnumUsers( g_pServerInfo, UserShowSet, (HANDLE)hFile); if (dwErr isnot NO_ERROR) { DisplayMessage( g_hModule, EMSG_UNABLE_TO_ENUM_USERS); } return dwErr; } BOOL UserShowReport( IN PRASUSER_DATA pUser, IN HANDLE hFile ) /*++ Routine Description: Prints ras user information to the display or a file if specified. This function can be used as a callback function (see UserEnumUsers). Arguments: pUser - The user hFile - The file Return Value: TRUE - continue enumeration FALSE - stop enumeration --*/ { DWORD dwErr, dwSize; WCHAR rgwcIfDesc[MAX_INTERFACE_NAME_LEN + 1]; PWCHAR pwszDialin = NULL, pwszCbPolicy = NULL, pwszCbNumber = NULL, pwszSetCmd = NULL; // Initialize the set command // pwszSetCmd = DMP_RASUSER_SET; // Initialize the dialin string // if (pUser->User0.bfPrivilege & RASPRIV_DialinPolicy) { pwszDialin = TOKEN_POLICY; } else if (pUser->User0.bfPrivilege & RASPRIV_DialinPrivilege) { pwszDialin = TOKEN_PERMIT; } else { pwszDialin = TOKEN_DENY; } // Initialize the callback policy string // if (pUser->User0.bfPrivilege & RASPRIV_NoCallback) { pwszCbPolicy = TOKEN_NONE; } else if (pUser->User0.bfPrivilege & RASPRIV_CallerSetCallback) { pwszCbPolicy = TOKEN_CALLER; } else { pwszCbPolicy = TOKEN_ADMIN; } // Initialize the callback number string // pwszCbNumber = pUser->User0.wszPhoneNumber; do { if(!pwszSetCmd or !pUser->pszUsername or !pwszDialin or !pwszCbNumber ) { DisplayError(NULL, ERROR_NOT_ENOUGH_MEMORY); break; } DisplayMessage(g_hModule, MSG_RASUSER_RASINFO, pUser->pszUsername, pwszDialin, pwszCbPolicy, pwszCbNumber); } while(FALSE); return TRUE; } BOOL UserShowSet( IN PRASUSER_DATA pUser, IN HANDLE hFile ) /*++ Routine Description: Prints ras user information to the display or a file if specified. This function can be used as a callback function (see UserEnumUsers). Arguments: pUser - The user hFile - The file Return Value: TRUE - continue enumeration FALSE - stop enumeration --*/ { DWORD dwErr, dwSize; WCHAR rgwcIfDesc[MAX_INTERFACE_NAME_LEN + 1]; PWCHAR pwszName = NULL, pwszDialin = NULL, pwszCbPolicy = NULL, pwszCbNumber = NULL, pwszSetCmd = NULL; // Initialize the set command // pwszSetCmd = DMP_RASUSER_SET; // Initialize the dialin string // if (pUser->User0.bfPrivilege & RASPRIV_DialinPolicy) { pwszDialin = RutlAssignmentFromTokens( g_hModule, TOKEN_DIALIN, TOKEN_POLICY); } else if (pUser->User0.bfPrivilege & RASPRIV_DialinPrivilege) { pwszDialin = RutlAssignmentFromTokens( g_hModule, TOKEN_DIALIN, TOKEN_PERMIT); } else { pwszDialin = RutlAssignmentFromTokens( g_hModule, TOKEN_DIALIN, TOKEN_DENY); } // Initialize the callback policy string // if (pUser->User0.bfPrivilege & RASPRIV_NoCallback) { pwszCbPolicy = RutlAssignmentFromTokens( g_hModule, TOKEN_CBPOLICY, TOKEN_NONE); } else if (pUser->User0.bfPrivilege & RASPRIV_CallerSetCallback) { pwszCbPolicy = RutlAssignmentFromTokens( g_hModule, TOKEN_CBPOLICY, TOKEN_CALLER); } else { pwszCbPolicy = RutlAssignmentFromTokens( g_hModule, TOKEN_CBPOLICY, TOKEN_CALLER); } // Initialize the callback number string // if (*(pUser->User0.wszPhoneNumber)) { pwszCbNumber = RutlAssignmentFromTokens( g_hModule, TOKEN_CBNUMBER, pUser->User0.wszPhoneNumber); } else { pwszCbNumber = NULL; } pwszName = RutlAssignmentFromTokens( g_hModule, TOKEN_NAME, pUser->pszUsername); do { if(!pwszSetCmd or !pwszName or !pwszDialin or !pwszCbPolicy ) { DisplayError(NULL, ERROR_NOT_ENOUGH_MEMORY); break; } DisplayMessage(g_hModule, MSG_RASUSER_SET_CMD, pwszSetCmd, pwszName, pwszDialin, pwszCbPolicy, (pwszCbNumber) ? pwszCbNumber : L""); } while(FALSE); // Callback { if (pwszDialin) { RutlFree(pwszDialin); } if (pwszCbPolicy) { RutlFree(pwszCbPolicy); } if (pwszCbNumber) { RutlFree(pwszCbNumber); } if (pwszName) { RutlFree(pwszName); } } return TRUE; } BOOL UserShowPermit( IN PRASUSER_DATA pUser, IN HANDLE hFile ) { if (pUser->User0.bfPrivilege & RASPRIV_DialinPrivilege) { return UserShowReport(pUser, hFile); } return TRUE; } DWORD UserEnumUsers( IN RASMON_SERVERINFO* pServerInfo, IN PFN_RASUSER_ENUM_CB pEnumFn, IN HANDLE hData ) /*++ Routine Description: Enumerates all users by calling the given callback function and passing it the user information and some user defined data. Enumeration stops when all the users have been enumerated or when the enumeration function returns FALSE. Arguments: pwszServer - The server on which the users should be enumerated pEnumFn - Enumeration function hData - Caller defined opaque data blob Return Value: NO_ERROR --*/ { DWORD dwErr, dwIndex = 0, dwCount = 100, dwEntriesRead, i; NET_DISPLAY_USER * pUsers; NET_API_STATUS nStatus; RAS_USER_0 RasUser0; HANDLE hUser = NULL; RASUSER_DATA UserData, *pUserData = &UserData; BOOL bInit = UserServerInfoIsInit(pServerInfo); UserServerInfoInit(pServerInfo); // Enumerate the users // while (TRUE) { // Read in the next block of user names nStatus = NetQueryDisplayInformation( pServerInfo->pszServer, 1, dwIndex, dwCount, dwCount * sizeof(NET_DISPLAY_USER), &dwEntriesRead, &pUsers); // Get out if there's an error getting user names if ((nStatus isnot NERR_Success) and (nStatus isnot ERROR_MORE_DATA)) { break; } for (i = 0; i < dwEntriesRead; i++) { // Initialize the user data ZeroMemory(pUserData, sizeof(RASUSER_DATA)); // Read in the old information dwErr = UserGetRasProperties ( pServerInfo, pUsers[i].usri1_name, &(pUserData->User0)); if (dwErr isnot NO_ERROR) { continue; } // Initialize the rest of the data structure pUserData->pszUsername = pUsers[i].usri1_name; pUserData->pszFullname = pUsers[i].usri1_full_name; // Call the enumeration callback if (! ((*(pEnumFn))(pUserData, hData))) { nStatus = NO_ERROR; break; } } // Set the index to read in the next set of users dwIndex = pUsers[dwEntriesRead - 1].usri1_next_index; // Free the users buffer NetApiBufferFree (pUsers); // If we've read in everybody, go ahead and break if (nStatus isnot ERROR_MORE_DATA) { break; } } if (!bInit) { UserServerInfoUninit(pServerInfo); } return NO_ERROR; }