1
/* Editor Settings: expandtabs and use 4 spaces for indentation
2
* ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: *
3
* -*- mode: c, c-basic-offset: 4 -*- */
6
* Copyright Likewise Software 2004-2008
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or (at
12
* your option) any later version.
14
* This program is distributed in the hope that it will be useful, but
15
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17
* for more details. You should have received a copy of the GNU General
18
* Public License along with this program. If not, see
19
* <http://www.gnu.org/licenses/>.
21
* LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
22
* TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
23
* WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
24
* TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
25
* GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU
26
* HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
27
* TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
28
* license@likewisesoftware.com
32
* Copyright (C) Likewise Software. All rights reserved.
40
* Likewise Security and Authentication Subsystem (LSASS)
42
* Active Directory Authentication Provider
44
* Authors: Danilo Almeida (dalmeida@likewisesoftware.com)
45
* Wei Fu (wfu@likewisesoftware.com)
49
#include "adprovider.h"
50
#include "batch_build.h"
52
typedef DWORD (*LSA_AD_BATCH_BUILDER_GET_ATTR_VALUE_CALLBACK)(
53
IN PVOID pCallbackContext,
56
OUT PVOID* ppFreeValueContext
59
typedef VOID (*LSA_AD_BATCH_BUILDER_FREE_VALUE_CONTEXT_CALLBACK)(
60
IN PVOID pCallbackContext,
61
IN OUT PVOID* ppFreeValueContext
64
typedef PVOID (*LSA_AD_BATCH_BUILDER_NEXT_ITEM_CALLBACK)(
65
IN PVOID pCallbackContext,
71
LsaAdBatchBuilderAppend(
72
IN OUT PDWORD pdwQueryOffset,
76
IN DWORD dwAppendLength
80
DWORD dwQueryOffset = *pdwQueryOffset;
81
DWORD dwNewQueryOffset = 0;
83
if (dwAppendLength > 0)
85
dwNewQueryOffset = dwQueryOffset + dwAppendLength;
86
if (dwNewQueryOffset < dwQueryOffset)
89
dwError = LW_ERROR_DATA_ERROR;
90
BAIL_ON_LSA_ERROR(dwError);
92
else if (dwNewQueryOffset - 1 >= dwQuerySize)
95
dwError = LW_ERROR_DATA_ERROR;
96
BAIL_ON_LSA_ERROR(dwError);
98
memcpy(pszQuery + dwQueryOffset, pszAppend, dwAppendLength);
99
pszQuery[dwNewQueryOffset] = 0;
100
*pdwQueryOffset = dwNewQueryOffset;
112
LsaAdBatchBuilderCreateQuery(
113
IN PCSTR pszQueryPrefix,
114
IN PCSTR pszQuerySuffix,
115
IN PCSTR pszAttributeName,
118
OUT PVOID* ppNextItem,
119
IN OPTIONAL PVOID pCallbackContext,
120
IN LSA_AD_BATCH_BUILDER_GET_ATTR_VALUE_CALLBACK pGetAttributeValueCallback,
121
IN OPTIONAL LSA_AD_BATCH_BUILDER_FREE_VALUE_CONTEXT_CALLBACK pFreeValueContextCallback,
122
IN LSA_AD_BATCH_BUILDER_NEXT_ITEM_CALLBACK pNextItemCallback,
123
IN DWORD dwMaxQuerySize,
124
IN DWORD dwMaxQueryCount,
125
OUT PDWORD pdwQueryCount,
130
PVOID pCurrentItem = NULL;
131
PSTR pszQuery = NULL;
132
PVOID pLastItem = pFirstItem;
133
const char szOrPrefix[] = "(|";
134
const char szOrSuffix[] = ")";
135
const DWORD dwOrPrefixLength = sizeof(szOrPrefix)-1;
136
const DWORD dwOrSuffixLength = sizeof(szOrSuffix)-1;
137
DWORD dwAttributeNameLength = strlen(pszAttributeName);
138
DWORD dwQuerySize = 0;
139
DWORD dwQueryCount = 0;
140
PVOID pFreeValueContext = NULL;
141
DWORD dwQueryPrefixLength = 0;
142
DWORD dwQuerySuffixLength = 0;
143
DWORD dwQueryOffset = 0;
144
DWORD dwSavedQueryCount = 0;
148
dwQueryPrefixLength = strlen(pszQueryPrefix);
152
dwQuerySuffixLength = strlen(pszQuerySuffix);
156
// prefix + orPrefix + <CONTENT> + orSuffix + suffix + NULL
157
dwQuerySize = dwQueryPrefixLength + dwOrPrefixLength + dwOrSuffixLength + dwQuerySuffixLength + 1;
159
pCurrentItem = pFirstItem;
160
while (pCurrentItem != pEndItem)
162
PCSTR pszAttributeValue = NULL;
164
if (pFreeValueContext)
166
pFreeValueContextCallback(pCallbackContext, &pFreeValueContext);
169
dwError = pGetAttributeValueCallback(
174
BAIL_ON_LSA_ERROR(dwError);
176
if (pszAttributeValue)
178
// "(" + attributeName + "=" + attributeValue + ")"
179
DWORD dwAttributeValueLength = strlen(pszAttributeValue);
180
DWORD dwItemLength = (1 + dwAttributeNameLength + 1 + dwAttributeValueLength + 1);
181
DWORD dwNewQuerySize = dwQuerySize + dwItemLength;
182
DWORD dwNewQueryCount = dwQueryCount + 1;
184
if (dwNewQuerySize < dwQuerySize)
187
dwError = LW_ERROR_DATA_ERROR;
188
BAIL_ON_LSA_ERROR(dwError);
190
if (dwMaxQuerySize && (dwNewQuerySize > dwMaxQuerySize))
194
if (dwMaxQueryCount && (dwNewQueryCount > dwMaxQueryCount))
198
dwQuerySize = dwNewQuerySize;
199
dwQueryCount = dwNewQueryCount;
202
pCurrentItem = pNextItemCallback(pCallbackContext, pCurrentItem);
204
pLastItem = pCurrentItem;
205
dwSavedQueryCount = dwQueryCount;
207
if (dwQueryCount < 1)
212
dwError = LwAllocateMemory(dwQuerySize, (PVOID*)&pszQuery);
213
BAIL_ON_LSA_ERROR(dwError);
218
dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize,
219
pszQueryPrefix, dwQueryPrefixLength);
220
BAIL_ON_LSA_ERROR(dwError);
222
dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize,
223
szOrPrefix, dwOrPrefixLength);
224
BAIL_ON_LSA_ERROR(dwError);
227
pCurrentItem = pFirstItem;
228
while (pCurrentItem != pLastItem)
230
PCSTR pszAttributeValue = NULL;
232
if (pFreeValueContext)
234
pFreeValueContextCallback(pCallbackContext, &pFreeValueContext);
237
dwError = pGetAttributeValueCallback(
242
BAIL_ON_LSA_ERROR(dwError);
244
if (pszAttributeValue)
246
DWORD dwAttributeValueLength = strlen(pszAttributeValue);
248
dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize,
250
BAIL_ON_LSA_ERROR(dwError);
252
dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize,
253
pszAttributeName, dwAttributeNameLength);
254
BAIL_ON_LSA_ERROR(dwError);
256
dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize,
258
BAIL_ON_LSA_ERROR(dwError);
260
dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize,
261
pszAttributeValue, dwAttributeValueLength);
262
BAIL_ON_LSA_ERROR(dwError);
264
dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize,
266
BAIL_ON_LSA_ERROR(dwError);
271
pCurrentItem = pNextItemCallback(pCallbackContext, pCurrentItem);
274
dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize,
275
szOrSuffix, dwOrSuffixLength);
276
BAIL_ON_LSA_ERROR(dwError);
278
dwError = LsaAdBatchBuilderAppend(&dwQueryOffset, pszQuery, dwQuerySize,
279
pszQuerySuffix, dwQuerySuffixLength);
280
BAIL_ON_LSA_ERROR(dwError);
282
assert(dwQueryOffset + 1 == dwQuerySize);
283
assert(dwSavedQueryCount == dwQueryCount);
286
// We handle error here instead of error label
287
// because there is a goto cleanup above.
290
LW_SAFE_FREE_STRING(pszQuery);
292
pLastItem = pFirstItem;
295
if (pFreeValueContext)
297
pFreeValueContextCallback(pCallbackContext, &pFreeValueContext);
300
*ppszQuery = pszQuery;
301
*pdwQueryCount = dwQueryCount;
302
*ppNextItem = pLastItem;
307
// Do not actually handle any errors here.
311
typedef struct _LSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT {
312
LSA_AD_BATCH_QUERY_TYPE QueryType;
313
BOOLEAN bIsForRealObject;
314
} LSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT, *PLSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT;
318
LsaAdBatchBuilderBatchItemGetAttributeValue(
319
IN PVOID pCallbackContext,
321
OUT PCSTR* ppszValue,
322
OUT PVOID* ppFreeValueContext
326
PLSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT pContext = (PLSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT)pCallbackContext;
327
LSA_AD_BATCH_QUERY_TYPE QueryType = pContext->QueryType;
328
BOOLEAN bIsForRealObject = pContext->bIsForRealObject;
329
PLSA_LIST_LINKS pLinks = (PLSA_LIST_LINKS)pItem;
330
PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks);
331
PSTR pszValueToEscape = NULL;
332
PSTR pszValueToHex = NULL;
333
PSTR pszValue = NULL;
334
PVOID pFreeValueContext = NULL;
335
// Free this on error only.
336
PSTR pszMatchTerm = NULL;
337
PSTR pszAllocatedMatchTermValue = NULL;
338
BOOLEAN bHaveReal = IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_REAL);
339
BOOLEAN bHavePseudo = IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_HAVE_PSEUDO);
341
if (IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM))
343
LW_SAFE_FREE_STRING(pBatchItem->pszQueryMatchTerm);
344
ClearFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM);
347
if ((bIsForRealObject && bHaveReal) ||
348
(!bIsForRealObject && bHavePseudo))
350
// This can only happen in the linked cells case, but even
351
// that should go away in the future as we just keep an
352
// unresolved batch items list.
354
LSA_ASSERT(!bIsForRealObject && (gpADProviderData->dwDirectoryMode == CELL_MODE));
360
case LSA_AD_BATCH_QUERY_TYPE_BY_DN:
361
// Must be looking for real object
362
LSA_ASSERT(bIsForRealObject);
363
LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type);
365
pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString;
366
LSA_ASSERT(pszValueToEscape);
369
case LSA_AD_BATCH_QUERY_TYPE_BY_SID:
370
if (pBatchItem->pszSid)
372
// This is case where we already got the SID by resolving
373
// the pseudo object by id/alias.
374
pszValue = pBatchItem->pszSid;
376
else if (QueryType == pBatchItem->QueryTerm.Type)
378
// This is the case where the original query was
380
pszValue = (PSTR)pBatchItem->QueryTerm.pszString;
381
LSA_ASSERT(pszValue);
383
// Will be NULL if we cannot find a SID for which to query.
384
// This can happen if this batch item is for an object
385
// that we did not find real but are trying to look up pseudo.
386
// In that case, we have NULL and will just skip it.
388
// If we have a SID string, make sure it looks like a SID.
389
// Note that we must do some sanity checking to make sure
390
// that the string does not need escaping since we are
391
// not setting pszValueToEscape. (The SID check takes
393
if (pszValue && !LsaAdBatchHasValidCharsForSid(pszValue))
396
dwError = LW_ERROR_INTERNAL;
397
BAIL_ON_LSA_ERROR(dwError);
400
if (bIsForRealObject)
402
// "S-"-style SID string are only handled starting with
403
// Windows 2003. So an LDAP hex-formatted SID string
404
// is needed to handle Windows 2000.
406
pszValueToHex = pszValue;
411
case LSA_AD_BATCH_QUERY_TYPE_BY_NT4:
412
LSA_ASSERT(bIsForRealObject);
413
if (pBatchItem->pszSamAccountName)
415
// Unprovisioned id/alias case where id mapper returned
416
// a SAM account name (and domain name) but no SID.
417
pszValueToEscape = pBatchItem->pszSamAccountName;
418
// However, we currently do not have this sort of id mapper
419
// support, so we LSA_ASSERT(FALSE) for now.
422
else if (QueryType == pBatchItem->QueryTerm.Type)
424
pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString;
425
LSA_ASSERT(pszValueToEscape);
429
case LSA_AD_BATCH_QUERY_TYPE_BY_UID:
430
case LSA_AD_BATCH_QUERY_TYPE_BY_GID:
431
LSA_ASSERT(!bIsForRealObject);
432
LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type);
434
dwError = LwAllocateStringPrintf(
435
&pszAllocatedMatchTermValue,
437
(unsigned int)pBatchItem->QueryTerm.dwId);
438
BAIL_ON_LSA_ERROR(dwError);
439
pszValue = pszAllocatedMatchTermValue;
441
// Note: It is ok to set this here because it is ok for
442
// this flag to be set if the match term field in the
443
// batch item is still NULL (i.e., if we fail later in
445
SetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM);
449
case LSA_AD_BATCH_QUERY_TYPE_BY_USER_ALIAS:
450
case LSA_AD_BATCH_QUERY_TYPE_BY_GROUP_ALIAS:
451
LSA_ASSERT(!bIsForRealObject);
452
LSA_ASSERT(QueryType == pBatchItem->QueryTerm.Type);
454
pszValueToEscape = (PSTR)pBatchItem->QueryTerm.pszString;
455
LSA_ASSERT(pszValueToEscape);
459
dwError = LW_ERROR_INVALID_PARAMETER;
460
BAIL_ON_LSA_ERROR(dwError);
463
LSA_ASSERT(!pszMatchTerm);
464
LSA_ASSERT(!(pszValueToEscape && pszValueToHex));
466
if (pszValueToEscape)
468
LSA_ASSERT(!pszValue);
469
dwError = LwLdapEscapeString(&pszValue, pszValueToEscape);
470
BAIL_ON_LSA_ERROR(dwError);
472
pszMatchTerm = pszValueToEscape;
473
pFreeValueContext = pszValue;
475
else if (pszValueToHex)
477
LSA_ASSERT(!pszValue);
478
dwError = LsaSidStrToLdapFormatHexStr(pszValueToHex, &pszValue);
479
BAIL_ON_LSA_ERROR(dwError);
481
pszMatchTerm = pszValueToHex;
482
pFreeValueContext = pszValue;
486
pszMatchTerm = pszValue;
490
// Note that the match value can be different from the value,
491
// which we may need to escape or hex.
492
pBatchItem->pszQueryMatchTerm = pszMatchTerm;
493
*ppszValue = pszValue;
494
*ppFreeValueContext = pFreeValueContext;
499
// assing output in cleanup in case of goto cleanup in function.
500
pszValueToEscape = NULL;
502
LW_SAFE_FREE_STRING(pFreeValueContext);
503
LW_SAFE_FREE_STRING(pszAllocatedMatchTermValue);
509
LsaAdBatchBuilderGenericFreeValueContext(
510
IN PVOID pCallbackContext,
511
IN OUT PVOID* ppFreeValueContext
514
LW_SAFE_FREE_MEMORY(*ppFreeValueContext);
519
LsaAdBatchBuilderBatchItemNextItem(
520
IN PVOID pCallbackContext,
524
PLSA_LIST_LINKS pLinks = (PLSA_LIST_LINKS)pItem;
528
#define AD_LDAP_QUERY_LW_USER "(keywords=objectClass=" AD_LDAP_CLASS_LW_USER ")"
529
#define AD_LDAP_QUERY_LW_GROUP "(keywords=objectClass=" AD_LDAP_CLASS_LW_GROUP ")"
530
#define AD_LDAP_QUERY_SCHEMA_USER "(objectClass=" AD_LDAP_CLASS_SCHEMA_USER ")"
531
#define AD_LDAP_QUERY_SCHEMA_GROUP "(objectClass=" AD_LDAP_CLASS_SCHEMA_GROUP ")"
532
#define AD_LDAP_QUERY_NON_SCHEMA "(objectClass=" AD_LDAP_CLASS_NON_SCHEMA ")"
533
#define AD_LDAP_QUERY_USER "(objectClass=User)"
534
#define AD_LDAP_QUERY_GROUP "(objectClass=Group)"
535
#define AD_LDAP_QUERY_DEFAULT_SCHEMA_ENABLED_USER "(uidNumber=*)"
536
#define AD_LDAP_QUERY_DEFAULT_SCHEMA_ENABLED_GROUP "(gidNumber=*)"
541
LsaAdBatchBuilderGetPseudoQueryPrefixInternal(
542
IN OPTIONAL PDWORD pdwDirectoryMode,
543
IN BOOLEAN bIsSchemaMode,
544
IN LSA_AD_BATCH_QUERY_TYPE QueryType,
545
IN LSA_AD_BATCH_OBJECT_TYPE ObjectType,
546
OUT PCSTR* ppszSuffix
549
PCSTR pszPrefix = NULL;
550
DWORD dwDirectoryMode = (pdwDirectoryMode == NULL ?
551
gpADProviderData->dwDirectoryMode :
554
if ((DEFAULT_MODE == dwDirectoryMode) && bIsSchemaMode)
556
if (LSA_AD_BATCH_QUERY_TYPE_BY_USER_ALIAS == QueryType ||
557
LSA_AD_BATCH_QUERY_TYPE_BY_GROUP_ALIAS == QueryType)
561
case LSA_AD_BATCH_OBJECT_TYPE_USER:
564
"(&" AD_LDAP_QUERY_USER AD_LDAP_QUERY_DEFAULT_SCHEMA_ENABLED_USER")"
567
case LSA_AD_BATCH_OBJECT_TYPE_GROUP:
570
"(&" AD_LDAP_QUERY_GROUP AD_LDAP_QUERY_DEFAULT_SCHEMA_ENABLED_GROUP")"
577
"(&" AD_LDAP_QUERY_USER AD_LDAP_QUERY_DEFAULT_SCHEMA_ENABLED_USER")"
578
"(&" AD_LDAP_QUERY_GROUP AD_LDAP_QUERY_DEFAULT_SCHEMA_ENABLED_GROUP")"
587
case LSA_AD_BATCH_OBJECT_TYPE_USER:
590
"(&" AD_LDAP_QUERY_USER ")"
593
case LSA_AD_BATCH_OBJECT_TYPE_GROUP:
596
"(&" AD_LDAP_QUERY_GROUP ")"
603
"(&" AD_LDAP_QUERY_USER ")"
604
"(&" AD_LDAP_QUERY_GROUP ")"
610
else if (bIsSchemaMode)
614
case LSA_AD_BATCH_OBJECT_TYPE_USER:
617
"(&" AD_LDAP_QUERY_SCHEMA_USER AD_LDAP_QUERY_LW_USER ")"
620
case LSA_AD_BATCH_OBJECT_TYPE_GROUP:
623
"(&" AD_LDAP_QUERY_SCHEMA_GROUP AD_LDAP_QUERY_LW_GROUP ")"
630
"(&" AD_LDAP_QUERY_SCHEMA_USER AD_LDAP_QUERY_LW_USER ")"
631
"(&" AD_LDAP_QUERY_SCHEMA_GROUP AD_LDAP_QUERY_LW_GROUP ")"
640
case LSA_AD_BATCH_OBJECT_TYPE_USER:
643
AD_LDAP_QUERY_NON_SCHEMA
644
AD_LDAP_QUERY_LW_USER
647
case LSA_AD_BATCH_OBJECT_TYPE_GROUP:
650
AD_LDAP_QUERY_NON_SCHEMA
651
AD_LDAP_QUERY_LW_GROUP
657
AD_LDAP_QUERY_NON_SCHEMA
659
AD_LDAP_QUERY_LW_USER
660
AD_LDAP_QUERY_LW_GROUP
666
*ppszSuffix = pszPrefix ? ")" : NULL;
672
LsaAdBatchBuilderGetPseudoQueryAttributeInternal(
673
IN OPTIONAL PDWORD pdwDirectoryMode,
674
IN BOOLEAN bIsSchemaMode,
675
IN LSA_AD_BATCH_QUERY_TYPE QueryType
678
PCSTR pszAttributeName = NULL;
682
case LSA_AD_BATCH_QUERY_TYPE_BY_SID:
684
pdwDirectoryMode != NULL && *pdwDirectoryMode == DEFAULT_MODE)
686
pszAttributeName = AD_LDAP_OBJECTSID_TAG;
690
pszAttributeName = "keywords=" AD_LDAP_BACKLINK_PSEUDO_TAG;
693
case LSA_AD_BATCH_QUERY_TYPE_BY_UID:
696
pszAttributeName = AD_LDAP_UID_TAG;
700
pszAttributeName = "keywords=" AD_LDAP_UID_TAG;
703
case LSA_AD_BATCH_QUERY_TYPE_BY_GID:
706
pszAttributeName = AD_LDAP_GID_TAG;
710
pszAttributeName = "keywords=" AD_LDAP_GID_TAG;
713
case LSA_AD_BATCH_QUERY_TYPE_BY_USER_ALIAS:
716
pszAttributeName = AD_LDAP_ALIAS_TAG;
720
pszAttributeName = "keywords=" AD_LDAP_ALIAS_TAG;
723
case LSA_AD_BATCH_QUERY_TYPE_BY_GROUP_ALIAS:
726
pszAttributeName = AD_LDAP_DISPLAY_NAME_TAG;
730
pszAttributeName = "keywords=" AD_LDAP_DISPLAY_NAME_TAG;
735
return pszAttributeName;
739
LsaAdBatchBuildQueryForRpc(
740
IN PCSTR pszNetbiosDomainName,
741
IN LSA_AD_BATCH_QUERY_TYPE QueryType,
742
// List of PLSA_AD_BATCH_ITEM
743
IN PLSA_LIST_LINKS pFirstLinks,
744
IN PLSA_LIST_LINKS pEndLinks,
745
OUT PLSA_LIST_LINKS* ppNextLinks,
746
IN DWORD dwMaxQueryCount,
747
OUT PDWORD pdwQueryCount,
748
OUT PSTR** pppszQueryList
752
PLSA_LIST_LINKS pLinks = NULL;
753
PSTR* ppszQueryList = NULL;
754
PLSA_LIST_LINKS pLastLinks = pFirstLinks;
755
DWORD dwQueryCount = 0;
756
DWORD dwSavedQueryCount = 0;
758
pLinks = pFirstLinks;
759
for (pLinks = pFirstLinks; pLinks != pEndLinks; pLinks = pLinks->Next)
761
PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks);
762
PCSTR pszQueryTerm = NULL;
766
case LSA_AD_BATCH_QUERY_TYPE_BY_SID:
768
if (pBatchItem->pszSid)
770
pszQueryTerm = pBatchItem->pszSid;
772
else if (QueryType == pBatchItem->QueryTerm.Type)
774
pszQueryTerm = pBatchItem->QueryTerm.pszString;
778
case LSA_AD_BATCH_QUERY_TYPE_BY_NT4:
780
if (pBatchItem->pszSamAccountName)
782
pszQueryTerm = pBatchItem->pszSamAccountName;
784
else if (QueryType == pBatchItem->QueryTerm.Type)
786
pszQueryTerm = pBatchItem->QueryTerm.pszString;
792
dwError = LW_ERROR_INTERNAL;
793
BAIL_ON_LSA_ERROR(dwError);
796
if (!LW_IS_NULL_OR_EMPTY_STR(pszQueryTerm))
798
DWORD dwNewQueryCount = dwQueryCount + 1;
800
if (dwMaxQueryCount && (dwNewQueryCount > dwMaxQueryCount))
804
dwQueryCount = dwNewQueryCount;
808
dwSavedQueryCount = dwQueryCount;
810
if (dwQueryCount < 1)
815
dwError = LwAllocateMemory(dwQueryCount*sizeof(*ppszQueryList), (PVOID*)&ppszQueryList);
816
BAIL_ON_LSA_ERROR(dwError);
819
// Loop until we reach last links.
820
for (pLinks = pFirstLinks; pLinks != pLastLinks; pLinks = pLinks->Next)
822
PLSA_AD_BATCH_ITEM pBatchItem = LW_STRUCT_FROM_FIELD(pLinks, LSA_AD_BATCH_ITEM, BatchItemListLinks);
824
if (IsSetFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM))
826
LW_SAFE_FREE_STRING(pBatchItem->pszQueryMatchTerm);
827
ClearFlag(pBatchItem->Flags, LSA_AD_BATCH_ITEM_FLAG_ALLOCATED_MATCH_TERM);
832
case LSA_AD_BATCH_QUERY_TYPE_BY_SID:
834
PCSTR pszUseSid = NULL;
835
if (pBatchItem->pszSid)
837
pszUseSid = pBatchItem->pszSid;
839
else if (QueryType == pBatchItem->QueryTerm.Type)
841
pszUseSid = pBatchItem->QueryTerm.pszString;
843
// We might not have a SID if we failed to find a pseudo.
846
dwError = LwAllocateString(pszUseSid,
847
&ppszQueryList[dwQueryCount++]);
848
BAIL_ON_LSA_ERROR(dwError);
849
pBatchItem->pszQueryMatchTerm = (PSTR)pszUseSid;
854
case LSA_AD_BATCH_QUERY_TYPE_BY_NT4:
856
PCSTR pszUseSamAccountName = NULL;
857
if (pBatchItem->pszSamAccountName)
859
pszUseSamAccountName = pBatchItem->pszSamAccountName;
861
else if (QueryType == pBatchItem->QueryTerm.Type)
863
pszUseSamAccountName = pBatchItem->QueryTerm.pszString;
865
if (pszUseSamAccountName)
867
dwError = LwAllocateStringPrintf(
868
&ppszQueryList[dwQueryCount++],
870
pszNetbiosDomainName,
871
pszUseSamAccountName);
872
BAIL_ON_LSA_ERROR(dwError);
873
pBatchItem->pszQueryMatchTerm = (PSTR)pszUseSamAccountName;
879
dwError = LW_ERROR_INTERNAL;
880
BAIL_ON_LSA_ERROR(dwError);
884
assert(dwSavedQueryCount == dwQueryCount);
887
// We handle error here instead of error label
888
// because there is a goto cleanup above.
891
LwFreeStringArray(ppszQueryList, dwSavedQueryCount);
893
dwSavedQueryCount = 0;
894
pLastLinks = pFirstLinks;
897
*pppszQueryList = ppszQueryList;
898
*pdwQueryCount = dwQueryCount;
899
*ppNextLinks = pLastLinks;
904
// Do not actually handle any errors here.
909
LsaAdBatchBuildQueryForReal(
910
IN LSA_AD_BATCH_QUERY_TYPE QueryType,
911
// List of PLSA_AD_BATCH_ITEM
912
IN PLSA_LIST_LINKS pFirstLinks,
913
IN PLSA_LIST_LINKS pEndLinks,
914
OUT PLSA_LIST_LINKS* ppNextLinks,
915
IN DWORD dwMaxQuerySize,
916
IN DWORD dwMaxQueryCount,
917
OUT PDWORD pdwQueryCount,
922
PLSA_LIST_LINKS pNextLinks = NULL;
923
DWORD dwQueryCount = 0;
924
PSTR pszQuery = NULL;
925
PCSTR pszAttributeName = NULL;
926
PCSTR pszPrefix = NULL;
927
LSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT context = { 0 };
931
case LSA_AD_BATCH_QUERY_TYPE_BY_DN:
932
pszAttributeName = AD_LDAP_DN_TAG;
934
case LSA_AD_BATCH_QUERY_TYPE_BY_SID:
935
pszAttributeName = AD_LDAP_OBJECTSID_TAG;
937
case LSA_AD_BATCH_QUERY_TYPE_BY_NT4:
938
pszAttributeName = AD_LDAP_SAM_NAME_TAG;
941
dwError = LW_ERROR_INVALID_PARAMETER;
942
BAIL_ON_LSA_ERROR(dwError);
945
// In Default/schema case, filter out disabled users
946
// when querying real objects.
947
if ((gpADProviderData->dwDirectoryMode == DEFAULT_MODE) &&
948
(gpADProviderData->adConfigurationMode == SchemaMode))
950
pszPrefix = "(&(|(&(objectClass=user)(uidNumber=*))(objectClass=group))(!(objectClass=computer))";
955
pszPrefix = "(&(|(objectClass=user)(objectClass=group))(!(objectClass=computer))";
957
/* Enable machine accounts in the unprovisioned provider.
958
This is needed for the srv driver in lwio. Clients frequently
959
connect using their machine account credentials for dfs referrals,
960
querying server capabilities, etc.... -- gcarter@likewise.com */
962
pszPrefix = "(&(|(objectClass=user)(&(objectClass=group)(groupType<=0)))";
966
context.QueryType = QueryType;
967
context.bIsForRealObject = TRUE;
969
dwError = LsaAdBatchBuilderCreateQuery(
977
LsaAdBatchBuilderBatchItemGetAttributeValue,
978
LsaAdBatchBuilderGenericFreeValueContext,
979
LsaAdBatchBuilderBatchItemNextItem,
984
BAIL_ON_LSA_ERROR(dwError);
987
*ppNextLinks = pNextLinks;
988
*pdwQueryCount = dwQueryCount;
989
*ppszQuery = pszQuery;
993
// set output on cleanup
994
pNextLinks = pFirstLinks;
996
LW_SAFE_FREE_STRING(pszQuery);
1002
LsaAdBatchBuildQueryForPseudoInternal(
1003
IN BOOLEAN bIsSchemaMode,
1004
IN OPTIONAL PDWORD pdwDirectoryMode,
1005
IN LSA_AD_BATCH_QUERY_TYPE QueryType,
1006
// List of PLSA_AD_BATCH_ITEM
1007
IN PLSA_LIST_LINKS pFirstLinks,
1008
IN PLSA_LIST_LINKS pEndLinks,
1009
OUT PLSA_LIST_LINKS* ppNextLinks,
1010
IN DWORD dwMaxQuerySize,
1011
IN DWORD dwMaxQueryCount,
1012
OUT PDWORD pdwQueryCount,
1017
PLSA_LIST_LINKS pNextLinks = NULL;
1018
DWORD dwQueryCount = 0;
1019
PSTR pszQuery = NULL;
1020
PCSTR pszAttributeName = NULL;
1021
PCSTR pszPrefix = NULL;
1022
PCSTR pszSuffix = NULL;
1023
LSA_AD_BATCH_BUILDER_BATCH_ITEM_CONTEXT context = { 0 };
1025
pszAttributeName = LsaAdBatchBuilderGetPseudoQueryAttributeInternal(
1029
if (!pszAttributeName)
1032
dwError = LW_ERROR_INVALID_PARAMETER;
1033
BAIL_ON_LSA_ERROR(dwError);
1036
pszPrefix = LsaAdBatchBuilderGetPseudoQueryPrefixInternal(
1040
LsaAdBatchGetObjectTypeFromQueryType(QueryType),
1043
if (!pszPrefix || !pszSuffix)
1046
dwError = LW_ERROR_INVALID_PARAMETER;
1047
BAIL_ON_LSA_ERROR(dwError);
1050
context.QueryType = QueryType;
1051
context.bIsForRealObject = FALSE;
1053
dwError = LsaAdBatchBuilderCreateQuery(
1059
(PVOID*)&pNextLinks,
1061
LsaAdBatchBuilderBatchItemGetAttributeValue,
1062
LsaAdBatchBuilderGenericFreeValueContext,
1063
LsaAdBatchBuilderBatchItemNextItem,
1068
BAIL_ON_LSA_ERROR(dwError);
1071
*ppNextLinks = pNextLinks;
1072
*pdwQueryCount = dwQueryCount;
1073
*ppszQuery = pszQuery;
1077
// set output on cleanup
1078
pNextLinks = pFirstLinks;
1080
LW_SAFE_FREE_STRING(pszQuery);
1085
LsaAdBatchBuildQueryForPseudo(
1086
IN BOOLEAN bIsSchemaMode,
1087
IN LSA_AD_BATCH_QUERY_TYPE QueryType,
1088
// List of PLSA_AD_BATCH_ITEM
1089
IN PLSA_LIST_LINKS pFirstLinks,
1090
IN PLSA_LIST_LINKS pEndLinks,
1091
OUT PLSA_LIST_LINKS* ppNextLinks,
1092
IN DWORD dwMaxQuerySize,
1093
IN DWORD dwMaxQueryCount,
1094
OUT PDWORD pdwQueryCount,
1098
return LsaAdBatchBuildQueryForPseudoInternal(
1112
LsaAdBatchBuildQueryForPseudoDefaultSchema(
1113
IN LSA_AD_BATCH_QUERY_TYPE QueryType,
1114
// List of PLSA_AD_BATCH_ITEM
1115
IN PLSA_LIST_LINKS pFirstLinks,
1116
IN PLSA_LIST_LINKS pEndLinks,
1117
OUT PLSA_LIST_LINKS* ppNextLinks,
1118
IN DWORD dwMaxQuerySize,
1119
IN DWORD dwMaxQueryCount,
1120
OUT PDWORD pdwQueryCount,
1124
DWORD dwDirectoryMode = DEFAULT_MODE;
1126
return LsaAdBatchBuildQueryForPseudoInternal(