Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
5.5 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // rasuser.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // This file defines the class RasUser.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 03/20/1998 Original version.
  16. // 04/24/1998 Allow null domain for local server.
  17. // 05/19/1998 Converted to NtSamHandler.
  18. // 06/03/1998 Always use RAS/MPR for local users.
  19. // 06/23/1998 Use DCLocator to find server.
  20. // 07/09/1998 Always use RasAdminUserGetInfo
  21. // 07/11/1998 Switch to IASGetRASUserInfo.
  22. // 07/28/1998 Handle case where IAS is running on a DC.
  23. // 08/10/1998 Fix initialization error codes.
  24. // 03/10/1999 Use LDAP when possible.
  25. // 03/23/1999 Store the user's DN.
  26. //
  27. ///////////////////////////////////////////////////////////////////////////////
  28. #include <ias.h>
  29. #include <iastlutl.h>
  30. #define IASSAMAPI
  31. #include <iaslsa.h>
  32. #include <iasntds.h>
  33. #include <iasparms.h>
  34. #include <sdoias.h>
  35. #include <rasuser.h>
  36. #include <userschema.h>
  37. //////////
  38. // Attributes that should be retrieved for each user.
  39. //////////
  40. const PCWSTR USER_PARMS[] =
  41. {
  42. L"userParameters",
  43. NULL
  44. };
  45. HRESULT RasUser::initialize() throw ()
  46. {
  47. //////////
  48. // Let's get everything that could fail out of the way first.
  49. //////////
  50. PIASATTRIBUTE attrs[3];
  51. DWORD error = IASAttributeAlloc(3, attrs);
  52. if (error) { return HRESULT_FROM_WIN32(error); }
  53. //////////
  54. // Initialize the dial-in bit attributes.
  55. //////////
  56. attrs[0]->dwId = IAS_ATTRIBUTE_ALLOW_DIALIN;
  57. attrs[0]->Value.itType = IASTYPE_BOOLEAN;
  58. attrs[0]->Value.Boolean = TRUE;
  59. attrs[1]->dwFlags = 0;
  60. allowAccess.attach(attrs[0], false);
  61. attrs[1]->dwId = IAS_ATTRIBUTE_ALLOW_DIALIN;
  62. attrs[1]->Value.itType = IASTYPE_BOOLEAN;
  63. attrs[1]->Value.Boolean = FALSE;
  64. attrs[1]->dwFlags = 0;
  65. denyAccess.attach(attrs[1], false);
  66. attrs[2]->dwId = RADIUS_ATTRIBUTE_SERVICE_TYPE;
  67. attrs[2]->Value.itType = IASTYPE_ENUM;
  68. attrs[2]->Value.Enumerator = 4;
  69. attrs[2]->dwFlags = IAS_INCLUDE_IN_ACCEPT;
  70. callbackFramed.attach(attrs[2], false);
  71. return S_OK;
  72. }
  73. void RasUser::finalize() throw ()
  74. {
  75. allowAccess.release();
  76. denyAccess.release();
  77. callbackFramed.release();
  78. }
  79. IASREQUESTSTATUS RasUser::processUser(
  80. IASRequest& request,
  81. PCWSTR domainName,
  82. PCWSTR username
  83. )
  84. {
  85. IASTraceString("Using downlevel dial-in parameters.");
  86. DWORD error;
  87. RAS_USER_0 ru0;
  88. // Try using LDAP first since it's fastest.
  89. PLDAPMessage res;
  90. error = IASNtdsQueryUserAttributes(
  91. domainName,
  92. username,
  93. LDAP_SCOPE_SUBTREE,
  94. const_cast<PWCHAR*>(USER_PARMS),
  95. &res
  96. );
  97. if (error == NO_ERROR)
  98. {
  99. // Retrieve the connection for this message.
  100. LDAP* ld = ldap_conn_from_msg(NULL, res);
  101. LDAPMessage* entry = ldap_first_entry(ld, res);
  102. if (entry)
  103. {
  104. // Store the user's DN.
  105. PWCHAR dn = ldap_get_dnW(ld, entry);
  106. IASStoreFQUserName(request, DS_FQDN_1779_NAME, dn);
  107. ldap_memfree(dn);
  108. // There is at most one attribute.
  109. PWCHAR *str = ldap_get_valuesW(
  110. ld,
  111. entry,
  112. const_cast<PWCHAR>(USER_PARMS[0])
  113. );
  114. // It's okay if we didn't get anything, the API can handle NULL
  115. // UserParameters.
  116. error = IASParmsQueryRasUser0((str ? *str : NULL), &ru0);
  117. ldap_value_freeW(str);
  118. }
  119. else
  120. {
  121. error = ERROR_NO_SUCH_USER;
  122. }
  123. ldap_msgfree(res);
  124. }
  125. else if (error == ERROR_DS_NOT_INSTALLED)
  126. {
  127. // No DS, so fall back to SAM APIs.
  128. error = IASGetRASUserInfo(username, domainName, &ru0);
  129. }
  130. if (error)
  131. {
  132. IASTraceFailure("Per-user attribute retrieval", error);
  133. HRESULT hr = IASMapWin32Error(error, IAS_SERVER_UNAVAILABLE);
  134. return IASProcessFailure(request, hr);
  135. }
  136. // Used for injecting single attributes.
  137. ATTRIBUTEPOSITION pos, *first, *last;
  138. first = &pos;
  139. last = first + 1;
  140. //////////
  141. // Insert the always present Allow-Dialin attribute.
  142. //////////
  143. if ((ru0.bfPrivilege & RASPRIV_DialinPrivilege) == 0)
  144. {
  145. first->pAttribute = denyAccess;
  146. }
  147. else
  148. {
  149. first->pAttribute = allowAccess;
  150. }
  151. IASTraceString("Inserting attribute msNPAllowDialin.");
  152. OverwriteAttribute(request, first, last);
  153. //////////
  154. // Insert the "Callback Framed" service type if callback is allowed.
  155. //////////
  156. if ((ru0.bfPrivilege & RASPRIV_CallbackType) != RASPRIV_NoCallback)
  157. {
  158. first->pAttribute = callbackFramed;
  159. IASTraceString("Inserting attribute msRADIUSServiceType.");
  160. OverwriteAttribute(request, first, last);
  161. }
  162. //////////
  163. // Insert the Callback-Number if present.
  164. //////////
  165. if (ru0.bfPrivilege & RASPRIV_AdminSetCallback)
  166. {
  167. IASAttribute callback(true);
  168. callback->dwId = RADIUS_ATTRIBUTE_CALLBACK_NUMBER;
  169. callback.setOctetString(ru0.wszPhoneNumber);
  170. callback.setFlag(IAS_INCLUDE_IN_ACCEPT);
  171. first->pAttribute = callback;
  172. IASTraceString("Inserting attribute msRADIUSCallbackNumber.");
  173. OverwriteAttribute(request, first, last);
  174. }
  175. IASTraceString("Successfully retrieved per-user attributes.");
  176. return IAS_REQUEST_STATUS_HANDLED;
  177. }