📄 waruserauthwin32nt.cpp
字号:
#include "StdAfx.h"#include "WarUserAuthWin32Nt.h" // class implemented#include "WarWinntLsa.h"#ifndef WAR_USER_AUTHDATA_WIN32_NT_H# include "WarUserAuthDataWin32Nt.h"#endif#ifndef WAR_LOG_H# include <WarLog.h>#endif#ifndef WAR_WIN32_NT_H# include "WarWin32Nt.h"#endif#ifndef WAR_INCLUDED_TCHAR_H# define WAR_INCLUDED_TCHAR_H# include <tchar.h>#endif#ifndef WAR_SVR_PROTOCOL_H# include "WarSvrProtocol.h"#endifusing namespace std;#ifdef UNICODE# define U2T(a) a#else# define U2T(a) WarCollector<char>(a).GetValue().c_str()#endif#define MY_SERVER (IsUsingLocalMachine() ? NULL : GetAuthServer().GetValue().c_str())/////////////////////////////// PUBLIC /////////////////////////////////////////============================= LIFECYCLE ====================================WarUserAuthWin32Nt::WarUserAuthWin32Nt()//: mAnonUserPasswd(netstr_t::SM_ERASE) {}// WarUserAuthWin32NtWarUserAuthWin32Nt::~WarUserAuthWin32Nt(){}// ~WarUserAuthWin32Nt//============================= OPERATORS ====================================//============================= OPERATIONS ===================================void WarUserAuthWin32Nt::Create(const WarWin32Registry& regKey, const bool doValidateGroup){ // Duplicate the regkey mRegRoot.Create(regKey.GetRef()); if (doValidateGroup) { // Fix FTP-group ValidateAndFixGroup(GetAuthGroup().GetValue()); ValidateAndCheckAnonUser(); }}WarUserAuthWin32Nt::WarLoginResultE WarUserAuthWin32Nt::Login( WarSvrProtocol& fromServer, war_ccsysstr_t virtualHost, war_ccsysstr_t userName, war_ccsysstr_t userPasswd, war_authdata_ptr_t& authDataPtr, bool &isAuthorative){ WarLog err_log(WARLOG_ERROR, "WarUserAuthWin32Nt::Login()"); WarLog debug_log(WARLOG_DEBUG, "WarUserAuthWin32Nt::Login()"); bool have_domain = false, is_anon = false; WarCollector<TCHAR> anon_username, anon_passwd(WarCollector<TCHAR>::SM_ERASE); if (!userName || !*userName) { if (IsAnonAllowed()) { if (!userPasswd || !*userPasswd) return LF_NEED_EMAIL_AS_PWD; anon_username << GetAnonUser().GetValue(); anon_passwd << GetAnonPasswd().GetValue(); userName = anon_username.GetValue().c_str(); userPasswd = anon_passwd.GetValue().c_str(); is_anon = true; } else { if (debug_log) { debug_log << "The NT/Windows 2000 auth module is configured not " "to allow anonymous logins. Passing the anonymous login " "request to the next auth handler." << war_endl; } return LF_CALLER_NOT_AUTHENTICATED; } } basic_string<TCHAR> name = userName; basic_string<TCHAR> domain = _T("."); string::size_type pos = name.find('@'); if (pos != string.npos) { // Domain is provided domain = name.substr(pos +1); name.erase(pos); have_domain = true; } WarCollector<TCHAR> login_name, login_domain, login_passwd(WarCollector<TCHAR>::SM_ERASE); login_name = name; login_domain = domain; login_passwd = userPasswd; HANDLE user_handle = NULL; // Check if the user exists in the "FTP-Users" group LPBYTE result_buffer = NULL; DWORD num_entries = 0, total_entries = 0; netstr_t net_username; if (have_domain) net_username << login_domain.GetValue() << '\\'; net_username << login_name.GetValue(); NET_API_STATUS net_result; if (!is_anon) { net_result = ::NetUserGetLocalGroups( MY_SERVER, net_username.GetValue().c_str(), 0, LG_INCLUDE_INDIRECT, &result_buffer, MAX_PREFERRED_LENGTH, &num_entries, &total_entries); netstr_t ftp_group = GetAuthGroup(); switch(net_result) { case NERR_Success: // Scan for the requiered group { PGROUP_USERS_INFO_0 pgroup = (PGROUP_USERS_INFO_0)result_buffer; for(DWORD i = 0; i < num_entries; i++, pgroup++) { if (::_wcsicmp(pgroup->grui0_name, ftp_group.GetValue().c_str()) == 0) break; } ::NetApiBufferFree(result_buffer); if (i == num_entries) { if (debug_log) { debug_log << "The user " << userName << " was found in the NT user database, but is " "denied access, as he/she is not a member " "of the local \"" << ftp_group.GetValue() << "\" group." << war_endl; } return LF_ACCESS_DENIED; } } break; case ERROR_ACCESS_DENIED: err_log << "The program is missing NT creditials to execute NetUserGetGroups(). NT authentication cannot be performed!" << WarError(WAR_ERR_SYSTEM_CALL_FAILED, ERROR_ACCESS_DENIED) << war_endl; WarThrow(WarError(WAR_ERR_SYSTEM_CALL_FAILED, ERROR_ACCESS_DENIED), NULL); break; case NERR_UserNotFound: if (debug_log) { debug_log << "The user " << userName << " was not found in the NT user database." << war_endl; } return LF_USER_NOT_FOUND; // Not found } } if (!userPasswd || !*userPasswd) return LF_NEED_PASSWORD; if (!::LogonUser((LPTSTR)login_name.GetValue().c_str(), (LPTSTR)login_domain.GetValue().c_str(), (LPTSTR)login_passwd.GetValue().c_str(), LOGON32_LOGON_BATCH, /*LOGON32_LOGON_NETWORK*/ LOGON32_PROVIDER_DEFAULT, &user_handle)) { if (debug_log) { WarSystemError system_err; debug_log << "The user " << userName << " was denied access. " << system_err << war_endl; if (system_err.SystemError() == ERROR_PRIVILEGE_NOT_HELD) { err_log << "Failed to authenticate the user due to " "a missing privilege. The most likely reason is " "that the process running the server is missing the " "\"Act as part of the operating system\" privilege. " "Please check the local security policy on the machine! " << system_err << war_endl; return LF_CONFIGURATION_ERROR; } } return LF_ACCESS_DENIED; } // Get the users SID SID_AND_ATTRIBUTES *psa = NULL; DWORD psa_len = 0; if (!::GetTokenInformation(user_handle, TokenUser, psa, 0, &psa_len)) { WarSystemError sys_err; if (sys_err.SystemError() != ERROR_INSUFFICIENT_BUFFER) { err_log << "user was authenticated, but the first call to GetTokenInformation() failed." << sys_err << war_endl; ::CloseHandle(user_handle); return LF_INTERNAL_ERROR; } } vector<char> psa_buf(psa_len); psa = (SID_AND_ATTRIBUTES *)&psa_buf[0]; if (!::GetTokenInformation(user_handle, TokenUser, psa, psa_len, &psa_len)) { WarSystemError sys_err; err_log << "user was authenticated, but the second call to GetTokenInformation() failed." << sys_err << war_endl; ::CloseHandle(user_handle); return LF_INTERNAL_ERROR; } try { user_data_ptr_t my_auth_ptr = CreateDataHandle(psa->Sid, userName, user_handle, is_anon); my_auth_ptr->LoadOptions(fromServer.GetProperties().mOptions); authDataPtr = (war_authdata_ptr_t &)my_auth_ptr; } catch(WarException) { // Clean up ::CloseHandle(user_handle); return LF_INTERNAL_ERROR; } // The user is logged on! if (debug_log) { debug_log << "The user "; if (is_anon) debug_log << "[anonymous] "; debug_log << userName << " has logged on to Windows NT/2000." << war_endl; } return LF_OK;}WarUserAuthWin32Nt::user_data_ptr_t WarUserAuthWin32Nt::CreateDataHandle(PSID pUserSid, war_ccsysstr_t userName, HANDLE hLoginHandle, bool isAnonymous) throw(WarException){ WarLog err_log(WARLOG_ERROR, "WarUserAuthWin32Nt::CreateDataHandle()"); // Open/create the users registry key TCHAR sid_string[MAX_PATH]; *sid_string = 0; DWORD sid_string_len = MAX_PATH; if (!WarGetTextualSid(pUserSid, sid_string, &sid_string_len)) { WarSystemError sys_err; err_log << "The call to GetTextualSid() failed." << sys_err << war_endl; WarThrow(sys_err, NULL); } WarUserAuthDataWin32Nt *pnew_win32handle = new WarUserAuthDataWin32Nt; try { pnew_win32handle->mLogonHandle = hLoginHandle; war_registrypath_t reg_path; reg_path << mRegRoot.GetRef().GetPath().GetPath() << WAR_SYSSLASH << WAR_WINNT_REG_USERS << WAR_SYSSLASH << sid_string; pnew_win32handle->mRegRoot.Create(WarWin32Registry::open_t( mRegRoot, reg_path)); pnew_win32handle->mRegRoot.SetValue(WAR_WINNT_REG_NAME, WarCollector<TCHAR>(userName).GetValue().c_str()); if (!pnew_win32handle->mRegRoot.HaveValue(WAR_WINNT_REG_ENABLE)) pnew_win32handle->mRegRoot.SetValue(WAR_WINNT_REG_ENABLE, true); WarCollector<char> user_name; if (isAnonymous) { user_name << "Anonymous"; } else { user_name << userName; } pnew_win32handle->SetUserName(user_name.GetValue().c_str()); pnew_win32handle->mIsAnonymous = isAnonymous; } catch(WarException& e) { delete pnew_win32handle; throw e; } return pnew_win32handle;}void WarUserAuthWin32Nt::SetUsingLocalMachine(const bool doSet) throw(WarException){ mRegRoot.SetValue(WAR_WINNT_AUTH_SERVER_LOCAL, doSet);}void WarUserAuthWin32Nt::SetAnonNeedEmailAsPasswd(const bool doSet) throw(WarException){ mRegRoot.SetValue(WAR_WINNT_AUTH_ANON_PWDEMAIL, doSet);}void WarUserAuthWin32Nt::SetEnableAnon(const bool doEnable) throw(WarException){ mRegRoot.SetValue(WAR_WINNT_AUTH_ALLOW_ANON, doEnable);}void WarUserAuthWin32Nt::SetAuthServer(const netstr_t& strName) throw(WarException){ ::RegSetValueExW(mRegRoot.GetNodeKey(), L"Auth Server", 0, REG_SZ, (LPBYTE)(strName.GetValue().c_str()), strName.GetValue().size() * sizeof(WCHAR));}void WarUserAuthWin32Nt::SetAuthGroup(const netstr_t& strName) throw(WarException){ ::RegSetValueExW(mRegRoot.GetNodeKey(), L"FTP Group", 0, REG_SZ, (LPBYTE)(strName.GetValue().c_str()), strName.GetValue().size() * sizeof(WCHAR));}void WarUserAuthWin32Nt::SetAnonUser(const netstr_t& strName) throw(WarException){ ::RegSetValueExW(mRegRoot.GetNodeKey(), L"Anonymous User", 0, REG_SZ, (LPBYTE)(strName.GetValue().c_str()), strName.GetValue().size() * sizeof(WCHAR));}void WarUserAuthWin32Nt::SetAnonPasswd(const netstr_t& strName) throw(WarException){ ::RegSetValueExW(mRegRoot.GetNodeKey(), L"Anonymous Password", 0, REG_SZ, (LPBYTE)(strName.GetValue().c_str()), strName.GetValue().size() * sizeof(WCHAR)); WarCollector<TCHAR> passwd_buf(WarCollector<wchar_t>::SM_ERASE); passwd_buf = strName; mRegRoot.SetValue(WAR_WINNT_AUTH_ANON_PASSWD, passwd_buf.GetValue(), true);}void WarUserAuthWin32Nt::CreateUser(war_ccsysstr_t userName, war_ccsysstr_t userPasswd, const bool doEnable) throw(WarException){ USER_INFO_1 ui; memset(&ui, 0, sizeof(ui)); netstr_t user_name = userName, user_passwd = userPasswd; ui.usri1_name = (LPWSTR)user_name.GetValue().c_str(); ui.usri1_password = (LPWSTR)user_passwd.GetValue().c_str(); ui.usri1_priv = USER_PRIV_USER; ui.usri1_flags = UF_SCRIPT | UF_DONT_EXPIRE_PASSWD | UF_DONT_REQUIRE_PREAUTH | UF_NORMAL_ACCOUNT; NET_API_STATUS result = ::NetUserAdd(MY_SERVER, 1, (LPBYTE)&ui, NULL); if (NERR_Success != result) { WarLog err_log(WARLOG_ERROR, "WarUserAuthWin32Nt::CreateUser()"); WarError err = MapErrorCode(result); err_log << "Failed to create user \"" << userName << "\". " << err << war_endl; WarThrow(err, NULL); }}void WarUserAuthWin32Nt::DeleteUser(war_ccsysstr_t userName)throw(WarException){ netstr_t user_name = userName; NET_API_STATUS result = ::NetUserDel( MY_SERVER, user_name.GetValue().c_str()); if (NERR_Success != result) { WarLog err_log(WARLOG_ERROR, "WarUserAuthWin32Nt::DeleteUser()"); WarError err = MapErrorCode(result); err_log << "Failed to delete user \""
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -