[PATCH] s4:drs Create connection object (nTDSConnection)

tridge at samba.org tridge at samba.org
Wed Nov 18 16:46:38 MST 2009

Hi Cristian,

 > I started doing the first part of this task - finding all the existing
 > connection objects - and I have some questions. I need to return a list of
 > connection objects from one function and pass it to another function to
 > apply the differences (add/remove the connections). how is this "list of
 > connection objects" represented in terms of data structure?

You could represent it in lots of possible ways. One fairly neat way
would be for you to declare some local structures like this:

 struct kcc_connection {
     struct GUID dsa_guid; /* the ntds GUID of the server */
     /* perhaps some other fields here? add whatever you find useful */

 struct kcc_connection_list {
     unsigned count;
     struct kcc_connection *servers;

you could also do it as a linked list if you prefer that.

 > I thought of a pointer to an array of ldb_dn, but I can't use
 > struct ldb_dn inside my code because the compiler complains of
 > "storage size of 'foo isn't known'. the definition of that
 > structure is on a .c file so I don't know what I should include to
 > use that struct. so I'm returning an array of ldb_dn pointers,

that's right, if you want a list of DNs then you should do something
like this:

  struct ldb_dn **dn_list;

Your code will only ever deal with opaque ldb_dn pointers, and not
deal with the internals of a struct ldb_dn itself. This is a very
common technique in C, and it is used to allow the ldb_dn.c code to
change the internals of the structure without affecting any external
code that uses a ldb_dn.

Doing the connection list as a list of ldb_dn pointers is a reasonable
approach, although I think that you'll find the code will turn out a
bit neater if you use local structures like I suggest above.

 > you said I should search the existing connection objects with
 > LDB_SCOPE_ONELEVEL. in my function, I'm searching for the nTDSDSA objects
 > (like the one in kccsrv_simple_update), but when I set the scope to ONELEVEL
 > it finds nothing.

What I meant is for you to search below each of the nTDSDSA objects
for connections. If you have a look at a windows server you'll see
that each nTDSDSA object (which represents a server) has a number of
nTDSDSAConnection objects directly below it in the hierarchy. 

I'd suggest you experiment a bit with ldbsearch on the commandline to
understand this better. On my test w2k8 system I would first do this:

  bin/ldbsearch -H ldap://w2k8 -b cn=configuration,dc=vsofs8,dc=com -Uadministrator%penguin objectclass=ntdsdsa dn

and I get back two records, one for each of the two DCs in the
domain. The two records I get are:

  # record 1
  dn: CN=NTDS Settings,CN=W2K8,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=vsofs8,DC=com

  # record 2
  dn: CN=NTDS Settings,CN=BLU,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=vsofs8,DC=com

now I want to see what connections the first server has. So, I do a
'onelevel' search below that object like this:

  bin/ldbsearch -H ldap://w2k8 -b 'CN=NTDS Settings,CN=W2K8,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=vsofs8,DC=com' -Uadministrator%penguin -s one objectclass=ntdsconnection dn

and I get back this:

  # record 1
  dn: CN=36319da5-ab68-4c97-adc7-1422f7b4f3da,CN=NTDS Settings,CN=W2K8,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=vsofs8,DC=com

It is that 2nd search that I was referring to. In the C code you are
writing you need a function that does this search for a given
server. It should probably take a ntds_guid as an argument. Then you'd
call this function, asking it to find the list of connections for our
own ntds_guid.

 > what type should I use to indicate return status? I see some functions
 > return the type int and other functions return the type NTSTATUS.

We use NTSTATUS in most places in Samba. For code that just does ldb
operations, we often use a 'int' instead and return LDB_ERR_* error

 > I investigated the problem but I can't find a solution to it. the process
 > goes very deep on the source code and when it gets to Samba events, I can't
 > understand it anymore. and I also found out that if I call
 > samdb_ntds_invocation_id() before adding the nTDSConnection object on the
 > domain (even if I don't add that value to the message), everything goes
 > fine.

I tried to reproduce this error using your git tree, but with the
ldb_msg_add_string() for "invocationID" removed from
kccsrv_create_connection(). I didn't see the error you have described.

I wonder what state your sam database is in? Have you perhaps
accidentally deleted or modified the nTDSDSA object? 

I'd suggest you rerun the vampire script to rejoin yourself to the
domain and try again. If you still get the error then I suggest you
debug it like this:

  1) at the point in the code where you get the error (ie. the goto
  failed) add this:

      DEBUG(0,("Fatal error, can't find my own invocationID - exiting\n"));

  2) then reproduce the problem. The samba server should exit when it
  hits the problem you describe.

  3) now your sam database is in the state where the search
  failed. Use bin/ldbsearch to investigate what is going wrong. You
  can do the same searches that the util.c code was doing on the
  command line. Have a look first at the dsServiceName attribute in
  the rootDSE like this:

    bin/ldbsearch -H $PREFIX/private/sam.ldb -s base -b '' dsServiceName

  does it return the DN of the NTDS Settings object for your server?
  For me it returns this:

     dsServiceName: CN=NTDS Settings,CN=BLU,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=vsofs8,DC=com

  (the above reproduces what samdb_ntds_settings_dn() does).

  4) if that works, then the next step is to reproduce what
  samdb_ntds_invocation_id() does. You'll see that the search it does
  takes the dsServiceName from the above as its baseDN. It then does
  this search:

    bin/ldbsearch -H $PREFIX/private/sam.ldb -s base -b 'CN=NTDS Settings,CN=BLU,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=vsofs8,DC=com' invocationId

  for me this returns this:

    invocationId: 443cd02a-afda-4668-8602-490639632cf4

  which is what is expected. The above search is exactly what is done
  in samdb_ntds_invocation_id(), so if that search fails in util.c
  then it should also fail on the command line. Does it? If it does,
  then try doing a subtree search under the CN=Servers tree. Does
  anything look wrong?

 > the updated code is on my git repo.

It is a good idea to keep your repo up to date with changes in the
upstream code. You would do this:

  git rebase origin/master

assuming that the upstream repository is called 'origin' for you, then
that will make your tree contain just your own changes, with your
changes moved to being at the top of the log. That makes it easier to
review, and also allows you to test that your changes haven't broken

Cheers, Tridge

More information about the samba-technical mailing list