Export (0) Print
Expand All

4.1.27.2 Server Behavior of the IDL_DRSVerifyNames Method

Informative summary of behavior: The server resolves each of a sequence of object names and returns its DSName and the values of zero or more of its attributes. The type of the input object name is indicated by the dwFlags field in the request. The IDL_DRSVerifyNames method verifies the names of both deleted and normal objects.

ULONG
IDL_DRSVerifyNames(
    [in, ref] DRS_HANDLE hDrs,
    [in] DWORD dwInVersion,
    [in, ref, switch_is(dwInVersion)]
        DRS_MSG_VERIFYREQ *pmsgIn,
    [out, ref] DWORD *pdwOutVersion,
    [out, ref, switch_is(*pdwOutVersion)]
        DRS_MSG_VERIFYREPLY *pmsgOut);

msgIn: DRS_MSG_VERIFYREQ_V1
msgOut:  DRS_MSG_VERIFYREPLY_V1
nc, d: DSName
o: sequence of DSName
i, j, k: int
domainName, username: unicodestring
done: boolean
attribute: ATTRTYP
FilterPAS: PARTIAL_ATTR_VECTOR_V1_EXT
GCPAS: PARTIAL_ATTR_VECTOR_V1_EXT
referredDomain: unicodestring

ValidateDRSInput(hDrs, 8)

pdwOutVersion^ := 1
pmsgOut^.V1.error := 0
pmsgOut^.V1.cNames := 0
pmsgOut^.V1.rpEntInf := null
pmsgOut^.V1.PrefixTable.PrefixCount := 0
pmsgOut^.V1.PrefixTable.pPrefixEntry := null


/* Perform input validation and access check */
if dwInVersion ≠ 0x1 then
  return ERROR_DS_DRA_INVALID_PARAMETER
endif
msgIn := pmsgIn^.V1
if  msgIn.dwFlags ≠ DRS_VERIFY_DSNAMES and 
    msgIn.dwFlags ≠ DRS_VERIFY_SAM_ACCOUNT_NAMES and
    msgIn.dwFlags ≠ DRS_VERIFY_SIDS and
    msgIn.dwFlags ≠ DRS_VERIFY_FPOS then
  return ERROR_DS_DRA_INVALID_PARAMETER
endif
if msgIn.cNames > 0 and msgIn.rpNames = null then
  return ERROR_DS_DRA_INVALID_PARAMETER
endif
if (msgIn.dwFlags = DRS_VERIFY_SIDS or 
    msgIn.dwFlags = DRS_VERIFY_SAM_ACCOUNT_NAMES or
    msgIn.dwFlags = DRS_VERIFY_FPOS) and
    not IsGC() then
  return ERROR_DS_GC_REQUIRED
endif
if msgIn.dwFlags = DRS_VERIFY_DSNAMES and not IsGC() then
  for i := 0 to msgIn.cNames-1
    if DefaultNC() ≠ GetObjectNC(msgIn.rpNames[i]^) then
      return ERROR_DS_GC_REQUIRED
    endif
  endfor
endif

/* Compute output */
msgOut.PrefixTable := dc.prefixTable
for i := 0 to msgIn.cNames - 1
  d := msgIn.rpNames[i]
  o := null
  done := false

  if msgIn.dwFlags = DRS_VERIFY_SAM_ACCOUNT_NAMES then
    domainName := DomainNameFromNT4AccountName(d.dn)
    username := UserNameFromNT4AccountName(d.dn)

    if domainName ≠ null and username ≠ null and 
        IsDomainNameInTrustedForest(domainName, referredDomain) then
      /* Provide a hint as to which forest this name could be coming
       * from. Note that 0xFFFF0009 is a hardcoded attribute ID
       * recognized by clients of this method. This attribute ID does
       * not correspond to any attribute defined in the schema. */
      msgOut.rpEntInf[i].pName := null
      msgOut.rpEntInf[i].AttrBlock.AttrCount := 1
      msgOut.rpEntInt[i].AttrBlock.pAttr[0].AttrTyp := 0xFFFF0009
      msgOut.rpEntInf[i].AttrBlock.pAttr[0].AttrVal.valCount := 1
      msgOut.rpEntInf[i].AttrBlock.pAttr[0].AttrVal.pAVal[0].valLen 
      := Length in characters of domainName, excluding any
         terminating null
      msgOut.rpEntInf[i].AttrBlock.pAttr[0].AttrVal.pAVal[0].pAVal :=
          referredDomain
      done := true
    endif
  endif

  if not done
    /* locate object or objects in question */
    if msgIn.dwFlags = DRS_VERIFY_DSNAMES then
      if ObjExists(d) then
        o := {d}
      endif 
    else if msgIn.dwFlags = DRS_VERIFY_SIDS then
      o := select all v from all-ts-included 
          where v!objectSid = d.sid and
           foreignSecurityPrincipal not in v!objectClass 
    else if msgIn.dwFlags = DRS_VERIFY_SAM_ACCOUNT_NAMES then
      if domainName ≠ null and username ≠ null then
        nc := select one v from all
            where v!nETBIOSName = domainName and GetObjectNC(v)= v 
        /* The following query returns both normal objects
           and tombstones */
        o := select all v from subtree-ts-included nc where
            v!sAMAccountName = username 
      else
        o := select all v from all-ts-included
            where v!userPrincipalName =
            d.dn 
      endif
    else if msgIn.dwFlags = DRS_VERIFY_FPOS then
      o := select all v from all-ts-included 
            where v!objectSid = d.sid
              and foreignSecurityPrincipal in v!objectClass
    endif

    /* Compute returned info and get requested attributes */
    if o.length = 1 and AccessCheckCAR(GetObjectNC(o[0]), DS-Replication-Get-Changes) then
      msgOut.rpEntInf[i].pName = o[0]!distinguishedName
      if MasterReplicaExists(GetObjectNC(o[0])) then
        msgOut.rpEntInf[i].ulFlags := ENTINF_FROM_MASTER
      else
        msgOut.rpEntEnf[i].ulFlags := 0
      endif
      msgOut.rpEntInf[i].AttrBlock.AttrCount :=
          msgIn.RequiredAttrs.AttrCount

      FilterPas := FilteredPAS()
      GCPas := GCPas()

      for j := 0 to msgIn.RequiredAttrs.AttrCount - 1

        if AmILHServer() then
          if (not (msgIn.RequiredAttrs.pAttr[j].AttrType in FilterPas
                   &&
                   msgIn.RequiredAttrs.pAttr[j].AttrType in GCPas))
            then
              /* skip requested attributes not part of both FilterPAS 
              and GCPas */
              msgOut.rpEntInf[i] := null
              continue;
          endif
        else
          /* pre-LH server */
          if (not (msgIn.RequiredAttrs.pAttr[j].AttrType in GCPas))
            then
              /* skip requested attributes not part of GCPas */
              msgOut.rpEntInf[i] := null
              continue;
          endif
        endif

        attribute := LocalAttidFromRemoteAttid(
                      msgIn.PrefixTable,
                      msgIn.RequiredAttrs.pAttr[j].attrTyp)
        msgOut.rpEntInf[i].AttrBlock.pAttr[j].attrTyp := attribute
        k := 0
        foreach val in GetAttrVals(o, attribute, false)
          msgOut.rpEntInf[i].AttrBlock.pAttr[j].AttrVal.pAVal :=
              ADR(ATTRVALFromValue(val,
                                   Syntax(attribute),
                                   dc.prefixTable))
          msgOut.rpEntInf[i].AttrBlock.pAttr[j].AttrVal.valCount :=
              k + 1
        endfor
      endfor
    else
      msgOut.rpEntInf[i] := null
    endif
  endif
endfor /* i := */

pmsgOut^.V1 := msgOut
return 0
 
Show:
© 2014 Microsoft