Export (0) Print
Expand All

4.1.10.5.12 ProcessFsmoRoleRequest

procedure ProcessFsmoRoleRequest(
  hDrs: DRS_HANDLE,
  msgIn: DRS_MSG_GETCHGREQ_V10,
  var msgOut: DRS_MSG_GETCHGREPLY_V6) 

Informative summary of behavior: The ProcessFsmoRoleRequest procedure performs the requested FSMO role operation indicated by msgIn.ulExtendedOp.

fsmoObj: DSName
clientDsaObj: DSName
serverObj: DSName: DSName
rodcObj: DSNAME: DSName
clientComputerObj: DSName
clientRidSetObj: DSName
ownerDsaObj: DSName
scope: set of DSName
ridAllocLoHi: ULONGLONG
ridAllocHi: DWORD
ridReqHi: DWORD
ridAvailLoHi: ULONGLONG
ridAvailLo: DWORD
ridAvailHi: DWORD
changedObjs: set of ObjAtts
changedLinks: set of ObjAttVal

/* Specific error check when at DC functional level Win2K3 */
if (DSAObj()!msDS-Behavior-Version = DS_BEHAVIOR_WIN2003) and
   (not DRS_WRIT_REP in msgIn.ulFlags) then
  msgOut.ulExtendedRet := EXOP_ERR_PARAM_ERR
  return
endif

fsmoObj := msgIn.pNC^
if not ObjExists(fsmoObj) then
  msgOut.ulExtendedRet := EXOP_ERR_UPDATE_ERR
  return
endif
if msgIn.uuidDsaObjDest = null then
    msgOut.ulExtendedRet := EXOP_ERR_UPDATE_ERR
  return
endif
clientDsaObj := select one o from ConfigNC()where
    o!objectGUID = msgIn.uuidDsaObjDest
if clientDsaObj = null then
  msgOut.ulExtendedRet := EXOP_ERR_UNKNOWN_CALLER
  return
endif

scope := {}if msgIn.ulExtendedOp in {EXOP_FSMO_REQ_ROLE, EXOP_FSMO_REQ_PDC,
    EXOP_FSMO_RID_REQ_ROLE} then
  /* Change the FSMO role owner from the server to the client. */
  if fsmoObj!fSMORoleOwner ≠ DSAObj() then
    msgOut.ulExtendedRet := EXOP_ERR_FSMO_NOT_OWNER
    return
  endif

  fsmoObj!fSMORoleOwner := clientDsaObj
  scope := GetRoleScope(fsmoObj)
else if msgIn.ulExtendedOp = EXOP_FSMO_ABANDON_ROLE then
  /* Request a change in the FSMO role owner from the current owner
   * to the server. The server will refuse to take the FSMO role if
    it is not a full replica and cannot own FSMO. */
     if AmIRODC() then
        msgOut.ulExtendedRet := EXOP_ERR_FSMO_REFUSING_ROLES
     endif

  if fsmoObj!fSMORoleOwner ≠ DSAObj() then
    ownerDsaObj := fsmoObj!fSMORoleOwner
    if not ObjExists(ownerDsaObj) then
      msgOut.ulExtendedRet := EXOP_ERR_UNKNOWN_CALLER
      return
    else if ownerDsaObj!isDeleted = true
      msgOut.ulExtendedRet := EXOP_ERR_OWNER_DELETED
      return
    endif

    Call IDL_DRSGetNCChanges as a client to the server identified by
        ownerDsaObj to perform a EXOP_FSMO_REQ_ROLE extended
        operation; see the client request generation and response
        processing sections

    if fsmoObj!fSMORoleOwner ≠ DSAObj() then
      /* Transfer failed. */
      msgOut.ulExtendedRet := EXOP_ERR_COULDNT_CONTACT
      return
    endif
  endif
else if msgIn.ulExtendedOp = EXOP_FSMO_REQ_RID_ALLOC then
  /* Allocate a block of RIDs for the client DC. */
  if fsmoObj ≠ DefaultNC()!rIDManagerReference then
    msgOut.ulExtendedRet := EXOP_ERR_MISMATCH
    return
  else if fsmoObj!fSMORoleOwner ≠ DSAObj() then
    msgOut.ulExtendedRet := EXOP_ERR_FSMO_NOT_OWNER
    return
  endif

  /* Locate or create the RID Set object for the client DC. */
  serverObj := clientDsaObj!parent
  clientComputerObj := serverObj!serverReference
  if clientComputerObj!rIDSetReference = null then
    clientRidSetObj := An implementation defined DSName in the
        default NC such that not ObjExists(clientRidSetObj)
    Create object with DSName clientRidSetObject such that
        rIDSet in clientRidSetObject!objectClass
    /* Windows Behavior: Windows sets clientRidSetObj to be a child
     * of clientComputerObj. */
    clientComputerObj!rIDSetReference := clientRidSetObj
  else
    clientRidSetObj := clientComputerObj!rIDSetReference
  endif
  /* Get the current RID allocation for the client DC. */
  ridAllocLoHi := clientRidSetObj!rIDAllocationPool
  ridAvailHi := most significant 32 bits of ridAvailLoHi
  ridReqHi := most significant 32 bits of msgIn.liFsmoInfo
  if ridAllocLoHi = 0 or ridAvailHi = 0 or ridReqHi ≥ ridAvailHi then
    /* The client DC has indeed exhausted its current allocation,
     * according to our records. */

    /* Get the range of RIDs that have not yet been allocated to any
     * DC. */
    ridAvailLoHi := fsmoObj!rIDAvailablePool
    ridAvailLo := least significant 32 bits of ridAvailLoHi
    ridAvailHi := most significant 32 bits of ridAvailLoHi

    /* Select a subset of the unallocated RIDs and allocate them to
     * the client. */
    Assign a value to ridAllocHi according to any implementation-
       defined policy such that ridAvailLo < ridAllocHi < ridAvailHi.
    /* Windows Behavior: By default, Windows sets ridAllocHi to
     * ridAvailLo + 500. */
    ridAllocLoHi := ridAvailLo as least significant 32 bits and
        ridAllocHi as most significant 32 bits
    ridAvailLo := ridAllocHi + 1
    ridAvailLoHi := ridAvailLo as least significant 32 bits and
        ridAvailHi as most significant 32 bits
    fsmoObj!rIDAvailablePool := ridAvailLoHi
    clientRidSetObj!rIDAllocationPool := ridAllocLoHi
    msgOut.liFsmoInfo := ridAllocLoHi
  endif

  scope := GetRoleScope(fsmoObj) + 
           {clientComputerObj, clientRidSetObj}
else if EXOP_REPL_SECRETS in msgIn.ulExtendedOp and
        AmILHServer() then
  /* Request replication of a single object with secret. 
   * Secret replication is allowed only if these three conditions
   * hold:
   *   1. Caller is an RODC. An RODC will always be a member of 
   *      "Enterprise Read-Only Domain Controllers" (RID 498) 
   *      [MS-ADTS] section 6.1.1.6.14.
   *   2. The object is configured to reveal secrets.
   *   3. Outbound secret replication is not disabled.
   */
    serverObj := clientDsaObj!parent
  rodcObj := serverObj!serverReference
  if CheckGroupMembership(
          GetCallerAuthorizationInfo(), SidFromStringSid("S-1-5-22"))
      and RevealSecretsForUserAllowed(rodcObj, fsmoObj)
      and (not NTDSDSA_OPT_DISABLE_OUTBOUND_REPL_SECRET
                in DSAObj()!options
           or DRS_SYNC_FORCED in msgIn.ulFlags) then 
    scope := {fsmoObj}
  else
    scope := {}
  endif
else if EXOP_REPL_OBJ in msgIn.ulExtendedOp
  if AmILHServer() = true and 
      NTDSDSA_OPT_DISABLE_OUTBOUND_REPL_OBJ in DSAObj()!options and
      not DRS_SYNC_FORCED in msgIn.ulFlags then
    /* replication of single object is disabled */
    pmsgOut.dwDRSError ERROR_DS_DRA_SOURCE_DISABLED
    return 
  endif

  /* Operation is invalid if destination is full replica but this server
   * is not, or if both are partial replicas but this server does not have
   * all the attributes needed by the destination in its PAS. */
  if(not FullReplicaExists(GetObjectNC(pMsgIn.NC)) and 
     not pMsgIn.pPartialAttrSet = null)
     msgOut.ulExtendedRet := EXOP_ERR_PARAM_ERR
     return
  else if not GetFilteredAttributeSet()∩ pMsgIn.pPartialAttrSet = {} then
     msgOut.ulExtendedRet := EXOP_ERR_PARAM_ERR
     return
  endif 

  scope := {fsmoObj}
else
  /* Unrecognized request. */
  msgOut.ulExtendedRet := EXOP_ERR_UNKNOWN_OP
  return
endif

if scope ≠ {} then
  /* Add updates in scope to the response. */
  GetChangesInScope(scope, msgIn.pUpToDateVecDest, msgIn.ulExtendedOp,
      msgIn.pPartialAttrSet, msgIn.pPartialAttrSet, 
      0, changedObjs, changedLinks)
  foreach o in changedObjs
    AddObjToResponse(
        hDrs, o, ncRoot, msgIn.ulFlags, msgIn.ulExtendedOp, msgOut)
  endfor
  foreach v in changedLinks
    AddLinkToResponse(v, msgIn, msgOut)
  endfor
endif

msgOut.ulExtendedRet := EXOP_ERR_SUCCESS
return
 
Show:
© 2014 Microsoft