/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1998, Microsoft Corp. All rights reserved. // // FILE // // rasuser.cpp // // SYNOPSIS // // This file defines the class RasUser. // // MODIFICATION HISTORY // // 03/20/1998 Original version. // 04/24/1998 Allow null domain for local server. // 05/19/1998 Converted to NtSamHandler. // 06/03/1998 Always use RAS/MPR for local users. // 06/23/1998 Use DCLocator to find server. // 07/09/1998 Always use RasAdminUserGetInfo // 07/11/1998 Switch to IASGetRASUserInfo. // 07/28/1998 Handle case where IAS is running on a DC. // 08/10/1998 Fix initialization error codes. // 03/10/1999 Use LDAP when possible. // 03/23/1999 Store the user's DN. // /////////////////////////////////////////////////////////////////////////////// #include #include #define IASSAMAPI #include #include #include #include #include #include ////////// // Attributes that should be retrieved for each user. ////////// const PCWSTR USER_PARMS[] = { L"userParameters", NULL }; HRESULT RasUser::initialize() throw () { ////////// // Let's get everything that could fail out of the way first. ////////// PIASATTRIBUTE attrs[3]; DWORD error = IASAttributeAlloc(3, attrs); if (error) { return HRESULT_FROM_WIN32(error); } ////////// // Initialize the dial-in bit attributes. ////////// attrs[0]->dwId = IAS_ATTRIBUTE_ALLOW_DIALIN; attrs[0]->Value.itType = IASTYPE_BOOLEAN; attrs[0]->Value.Boolean = TRUE; attrs[1]->dwFlags = 0; allowAccess.attach(attrs[0], false); attrs[1]->dwId = IAS_ATTRIBUTE_ALLOW_DIALIN; attrs[1]->Value.itType = IASTYPE_BOOLEAN; attrs[1]->Value.Boolean = FALSE; attrs[1]->dwFlags = 0; denyAccess.attach(attrs[1], false); attrs[2]->dwId = RADIUS_ATTRIBUTE_SERVICE_TYPE; attrs[2]->Value.itType = IASTYPE_ENUM; attrs[2]->Value.Enumerator = 4; attrs[2]->dwFlags = IAS_INCLUDE_IN_ACCEPT; callbackFramed.attach(attrs[2], false); return S_OK; } void RasUser::finalize() throw () { allowAccess.release(); denyAccess.release(); callbackFramed.release(); } IASREQUESTSTATUS RasUser::processUser( IASRequest& request, PCWSTR domainName, PCWSTR username ) { IASTraceString("Using downlevel dial-in parameters."); DWORD error; RAS_USER_0 ru0; // Try using LDAP first since it's fastest. PLDAPMessage res; error = IASNtdsQueryUserAttributes( domainName, username, LDAP_SCOPE_SUBTREE, const_cast(USER_PARMS), &res ); if (error == NO_ERROR) { // Retrieve the connection for this message. LDAP* ld = ldap_conn_from_msg(NULL, res); LDAPMessage* entry = ldap_first_entry(ld, res); if (entry) { // Store the user's DN. PWCHAR dn = ldap_get_dnW(ld, entry); IASStoreFQUserName(request, DS_FQDN_1779_NAME, dn); ldap_memfree(dn); // There is at most one attribute. PWCHAR *str = ldap_get_valuesW( ld, entry, const_cast(USER_PARMS[0]) ); // It's okay if we didn't get anything, the API can handle NULL // UserParameters. error = IASParmsQueryRasUser0((str ? *str : NULL), &ru0); ldap_value_freeW(str); } else { error = ERROR_NO_SUCH_USER; } ldap_msgfree(res); } else if (error == ERROR_DS_NOT_INSTALLED) { // No DS, so fall back to SAM APIs. error = IASGetRASUserInfo(username, domainName, &ru0); } if (error) { IASTraceFailure("Per-user attribute retrieval", error); HRESULT hr = IASMapWin32Error(error, IAS_SERVER_UNAVAILABLE); return IASProcessFailure(request, hr); } // Used for injecting single attributes. ATTRIBUTEPOSITION pos, *first, *last; first = &pos; last = first + 1; ////////// // Insert the always present Allow-Dialin attribute. ////////// if ((ru0.bfPrivilege & RASPRIV_DialinPrivilege) == 0) { first->pAttribute = denyAccess; } else { first->pAttribute = allowAccess; } IASTraceString("Inserting attribute msNPAllowDialin."); OverwriteAttribute(request, first, last); ////////// // Insert the "Callback Framed" service type if callback is allowed. ////////// if ((ru0.bfPrivilege & RASPRIV_CallbackType) != RASPRIV_NoCallback) { first->pAttribute = callbackFramed; IASTraceString("Inserting attribute msRADIUSServiceType."); OverwriteAttribute(request, first, last); } ////////// // Insert the Callback-Number if present. ////////// if (ru0.bfPrivilege & RASPRIV_AdminSetCallback) { IASAttribute callback(true); callback->dwId = RADIUS_ATTRIBUTE_CALLBACK_NUMBER; callback.setOctetString(ru0.wszPhoneNumber); callback.setFlag(IAS_INCLUDE_IN_ACCEPT); first->pAttribute = callback; IASTraceString("Inserting attribute msRADIUSCallbackNumber."); OverwriteAttribute(request, first, last); } IASTraceString("Successfully retrieved per-user attributes."); return IAS_REQUEST_STATUS_HANDLED; }