• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: LDAP
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: LDAP


  • Subject: Re: LDAP
  • From: Quinn <email@hidden>
  • Date: Fri, 11 Nov 2005 10:53:36 +0000

At 9:16 +0000 11/11/05, Martin Crane wrote:
Sorry, maybe I phrased my original question badly. I don't want to authenticate the user, as seems to be the requirement in the CryptNoMore sample. I simply want to find out the server which already authenticated the user at the Login Window and retrieve its LDAP search base - that which is set either in the Directory Access app or supplied via a DHCP offer.

Right. My point in directing you to CryptNoMore is that:

a) you need to find out which directory node (that is, which LDAP server) authenticated the user

b) CryptNoMore gets that information (the AppleMetaNodeLocation attribute of the user's Directory Services record) as part of its operation

c) the Directory Services API is complex, so it's better for you to start with CryptNoMore than to try and figure it out from scratch yourself

I answered a similar question for a developer quite recently. They were doing advanced printer authentication, and wanted to know, for a given user ID, whether that user was authenticated via Active Directory and, if so, what their Active Directory user name and Active Directory domain was. Sounds similar, huh?

I solved this problem by starting with CryptNoMore and bashing the code until it returned the attributes I needed. The vast bulk of the code didn't change. I've included the new code at the end of this email.

[btw Just for the record, the technique shown in this code is slightly wrong. After consulting with Apple's Active Directory DS plugin engineer, we decided that the best solution for getting the AD domain is to simply string the "/Active Directory/" from the front of the AppleMetaNodeLocation attribute's value. This is preferred over accessing the "dsAttrTypeNative:ADDomain" attribute. However, this change is highly AD specific, and thus irrelevant to my proposed solution to your LDAP problem.]

S+E
--
Quinn "The Eskimo!"                    <http://www.apple.com/developer/>
Apple Developer Technical Support * Networking, Communications, Hardware

static tDirStatus FindUsersADInfo(
    tDirReference       dirRef,
    tDirNodeReference   nodeRef,
    const char *        username,
    char **             adNamePtr,
    char **             adDomainPtr
)
    // Finds the authentication information for a given user.
    // dirRef is the connection to Open Directory.
    // nodeRef is the node to use to do the searching.  Typically
    // this is the authentication search node, whose path is found
    // using GetSearchNodePathList.  username is the user whose
    // information we're looking for.
    //
    // On success, *pathListToAuthNodePtr is a data list that
    // contain's the path components of the authentication node
    // for the specified user.
    // On success, *userNameForAuthPtr contains a pointer to C string
    // that is the user's name for authentication.  This can be
    // different from username.  For example, if user's long name is
    // "Mr Gumby" and their short name is "mrgumby", username can be
    // either the long name or the short name, but *userNameForAuthPtr
    // will always be the short name.  The caller is responsible for
    // freeing this string using free.
{
    tDirStatus          err;
    tDirStatus          junk;
    tDataBufferPtr      buf;
    tDataListPtr        recordType;
    tDataListPtr        recordName;
    tDataListPtr        requestedAttributes;
    unsigned long       recordCount;
    tAttributeListRef   foundRecAttrList;
    tContextData        context;
    tRecordEntryPtr     foundRecEntry;
    char *              adName;
    char *              adDomain;

    assert(dirRef != 0);
    assert(nodeRef != 0);
    assert(username != NULL);
    assert( adNamePtr != NULL);
    assert(*adNamePtr == NULL);
    assert( adDomainPtr != NULL);
    assert(*adDomainPtr == NULL);

recordType = NULL;
recordName = NULL;
requestedAttributes = NULL;
foundRecAttrList = 0;
context = NULL;
foundRecEntry = NULL;
adName = NULL;
adDomain = NULL;
// Allocate a buffer for the record results. We'll grow this
// buffer if it proves to be too small.
err = eDSNoErr;
buf = dsDataBufferAllocate(dirRef, kDefaultDSBufferSize);
if (buf == NULL) {
err = eDSAllocationFailed;
}


// Create the information needed for the search. We're searching for
// a record of type kDSStdRecordTypeUsers whose name is "username". // We want to get back the kDSNAttrMetaNodeLocation and kDSNAttrRecordName
// attributes.
if (err == eDSNoErr) {
recordType = dsBuildListFromStrings(dirRef, kDSStdRecordTypeUsers, NULL);
recordName = dsBuildListFromStrings(dirRef, username, NULL);
requestedAttributes = dsBuildListFromStrings(dirRef, "dsAttrTypeNative:sAMAccountName", "dsAttrTypeNative:ADDomain", NULL);


if ( (recordType == NULL) || (recordName == NULL) || (requestedAttributes == NULL) ) {
err = eDSAllocationFailed;
}
}
// Search for a matching record.
if (err == eDSNoErr) {
recordCount = 1; // we only want one match (the first)
err = dsGetRecordListQ(
dirRef,
nodeRef,
&buf,
recordName,
eDSExact,
recordType,
requestedAttributes,
false,
&recordCount,
&context
);
}
if ( (err == eDSNoErr) && (recordCount < 1) ) {
err = eDSRecordNotFound;
}
// Get the first record from the search. Then enumerate the attributes for
// that record. For each attribute, extract the first value (remember that
// attributes can by multi-value). Then see if the attribute is one that
// we care about. If it is, remember the value for later processing.
if (err == eDSNoErr) {
assert(recordCount == 1); // we only asked for one record, shouldn't get more back


err = dsGetRecordEntry(nodeRef, buf, 1, &foundRecAttrList, &foundRecEntry);
}
if (err == eDSNoErr) {
unsigned long attrIndex;
// Iterate over the attributes.
for (attrIndex = 1; attrIndex <= foundRecEntry->fRecordAttributeCount; attrIndex++) {
tAttributeValueListRef thisValue;
tAttributeEntryPtr thisAttrEntry;
tAttributeValueEntryPtr thisValueEntry;
const char * thisAttrName;
thisValue = 0;
thisAttrEntry = NULL;
thisValueEntry = NULL;
// Get the information for this attribute.
err = dsGetAttributeEntry(nodeRef, buf, foundRecAttrList, attrIndex, &thisValue, &thisAttrEntry);


            if (err == eDSNoErr) {
                thisAttrName = thisAttrEntry->fAttributeSignature.fBufferData;

// We only care about attributes that have values.
if (thisAttrEntry->fAttributeValueCount > 0) {


// Get the first value for this attribute. This is common code for
// the two potential attribute values listed below, so we do it first.


err = dsGetAttributeValue(nodeRef, buf, 1, thisValue, &thisValueEntry);
if (err == eDSNoErr) {
const char * thisValueDataPtr;
unsigned long thisValueDataLen;


thisValueDataPtr = thisValueEntry->fAttributeValueData.fBufferData;
thisValueDataLen = thisValueEntry->fAttributeValueData.fBufferLength;


// Handle each of the two attributes we care about; ignore any others.
if ( strcmp(thisAttrName, "dsAttrTypeNative:sAMAccountName") == 0 ) {
assert(adName == NULL); // same attribute twice


adName = (char *) malloc( thisValueDataLen + 1 );
if (adName == NULL) {
err = eDSAllocationFailed;
} else {
memcpy(
adName,
thisValueDataPtr,
thisValueDataLen
);
adName[thisValueDataLen] = 0; // terminating null
}
} else if ( strcmp(thisAttrName, "dsAttrTypeNative:ADDomain") == 0 ) {
assert(adDomain == NULL); // same attribute twice
adDomain = (char *) malloc( thisValueDataLen + 1 );
if (adDomain == NULL) {
err = eDSAllocationFailed;
} else {
memcpy(
adDomain,
thisValueDataPtr,
thisValueDataLen
);
adDomain[thisValueDataLen] = 0; // terminating null
}
} else {
fprintf(stderr, "FindUsersADInfo: Unexpected attribute '%s'.", thisAttrName);
}
}
} else {
fprintf(stderr, "FindUsersADInfo: Unexpected no-value attribute '%s'.", thisAttrName);
}
}


// Clean up.
if (thisValueEntry != NULL) {
junk = dsDeallocAttributeValueEntry(dirRef, thisValueEntry);
assert(junk == eDSNoErr);
}
if (thisValue != 0) {
junk = dsCloseAttributeValueList(thisValue);
assert(junk == eDSNoErr);
}
if (thisAttrEntry != NULL) {
junk = dsDeallocAttributeEntry(dirRef, thisAttrEntry);
assert(junk == eDSNoErr);
}
if (err != eDSNoErr) {
break;
}
}
}
// Copy results out to caller.
if (err == eDSNoErr) {
if ( (adName != NULL) && (adDomain != NULL) ) {
// Copy out results.
*adNamePtr = adName;
*adDomainPtr = adDomain;
// NULL out locals so that we don't dispose them.
adName = NULL;
adDomain = NULL;
} else {
err = eDSAttributeNotFound;
}
}


    // Clean up.

free(adName); // on success, this is NULLed out above, so it doesn't actually free the result
free(adDomain); // on success, this is NULLed out above, so it doesn't actually free the result
if (foundRecAttrList != 0) {
junk = dsCloseAttributeList(foundRecAttrList);
assert(junk == eDSNoErr);
}
if (context != NULL) {
junk = dsReleaseContinueData(dirRef, context);
assert(junk == eDSNoErr);
}
if (foundRecAttrList != 0) {
junk = dsDeallocRecordEntry(dirRef, foundRecEntry);
assert(junk == eDSNoErr);
}
if (requestedAttributes != NULL) {
junk = dsDataListAndHeaderDeallocate(dirRef, requestedAttributes);
assert(junk == eDSNoErr);
}
if (recordName != NULL) {
junk = dsDataListAndHeaderDeallocate(dirRef, recordName);
assert(junk == eDSNoErr);
}
if (recordType != NULL) {
junk = dsDataListAndHeaderDeallocate(dirRef, recordType);
assert(junk == eDSNoErr);
}
if (buf != NULL) {
junk = dsDataBufferDeAllocate(dirRef, buf);
assert(junk == eDSNoErr);
}


assert( (err == eDSNoErr) == ( (*adNamePtr != NULL) && (*adDomainPtr != NULL) ) );

    return err;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: LDAP
      • From: Martin Crane <email@hidden>
References: 
 >Intercepting IPv6 ND packets (From: Jonathan Wood <email@hidden>)
 >Re: Intercepting IPv6 ND packets (From: "Peter Lovell" <email@hidden>)
 >Re: Intercepting IPv6 ND packets (From: Jonathan Wood <email@hidden>)
 >Re: Intercepting IPv6 ND packets (From: Josh Graessley <email@hidden>)
 >Re: Intercepting IPv6 ND packets (From: Jonathan Wood <email@hidden>)
 >LDAP (From: Martin Crane <email@hidden>)
 >Re: LDAP (From: Quinn <email@hidden>)
 >Re: LDAP (From: Martin Crane <email@hidden>)

  • Prev by Date: Re: LDAP
  • Next by Date: Re: LDAP
  • Previous by thread: Re: LDAP
  • Next by thread: Re: LDAP
  • Index(es):
    • Date
    • Thread