root/source3/winbindd/idmap_ad.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ad_idmap_cached_connection_internal
  2. ad_idmap_cached_connection
  3. idmap_ad_initialize
  4. find_map_by_id
  5. find_map_by_sid
  6. idmap_ad_unixids_to_sids
  7. idmap_ad_sids_to_unixids
  8. idmap_ad_close
  9. ad_map_type_string
  10. nss_ad_generic_init
  11. nss_sfu_init
  12. nss_sfu20_init
  13. nss_rfc2307_init
  14. nss_ad_get_info
  15. nss_ad_map_to_alias
  16. nss_ad_map_from_alias
  17. nss_ad_close
  18. idmap_ad_init

   1 /*
   2  *  idmap_ad: map between Active Directory and RFC 2307 or "Services for Unix" (SFU) Accounts
   3  *
   4  * Unix SMB/CIFS implementation.
   5  *
   6  * Winbind ADS backend functions
   7  *
   8  * Copyright (C) Andrew Tridgell 2001
   9  * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
  10  * Copyright (C) Gerald (Jerry) Carter 2004-2007
  11  * Copyright (C) Luke Howard 2001-2004
  12  * Copyright (C) Michael Adam 2008
  13  *
  14  * This program is free software; you can redistribute it and/or modify
  15  * it under the terms of the GNU General Public License as published by
  16  * the Free Software Foundation; either version 3 of the License, or
  17  * (at your option) any later version.
  18  *
  19  * This program is distributed in the hope that it will be useful,
  20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22  * GNU General Public License for more details.
  23  *
  24  * You should have received a copy of the GNU General Public License
  25  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  26  */
  27 
  28 #include "includes.h"
  29 #include "winbindd.h"
  30 
  31 #undef DBGC_CLASS
  32 #define DBGC_CLASS DBGC_IDMAP
  33 
  34 #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
  35 
  36 #define IDMAP_AD_MAX_IDS 30
  37 #define CHECK_ALLOC_DONE(mem) do { \
  38      if (!mem) { \
  39            DEBUG(0, ("Out of memory!\n")); \
  40            ret = NT_STATUS_NO_MEMORY; \
  41            goto done; \
  42       } \
  43 } while (0)
  44 
  45 struct idmap_ad_context {
  46         uint32_t filter_low_id;
  47         uint32_t filter_high_id;
  48         ADS_STRUCT *ads;
  49         struct posix_schema *ad_schema;
  50         enum wb_posix_mapping ad_map_type; /* WB_POSIX_MAP_UNKNOWN */
  51 };
  52 
  53 NTSTATUS init_module(void);
  54 
  55 /************************************************************************
  56  ***********************************************************************/
  57 
  58 static ADS_STATUS ad_idmap_cached_connection_internal(struct idmap_domain *dom)
     /* [<][>][^][v][top][bottom][index][help] */
  59 {
  60         ADS_STRUCT *ads;
  61         ADS_STATUS status;
  62         bool local = False;
  63         fstring dc_name;
  64         struct sockaddr_storage dc_ip;
  65         struct idmap_ad_context *ctx;
  66         char *ldap_server = NULL;
  67         char *realm = NULL;
  68         struct winbindd_domain *wb_dom;
  69 
  70         DEBUG(10, ("ad_idmap_cached_connection: called for domain '%s'\n",
  71                    dom->name));
  72 
  73         ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
  74 
  75         if (ctx->ads != NULL) {
  76 
  77                 time_t expire;
  78                 time_t now = time(NULL);
  79 
  80                 ads = ctx->ads;
  81 
  82                 expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
  83 
  84                 /* check for a valid structure */
  85                 DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
  86                           (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));
  87 
  88                 if ( ads->config.realm && (expire > time(NULL))) {
  89                         return ADS_SUCCESS;
  90                 } else {
  91                         /* we own this ADS_STRUCT so make sure it goes away */
  92                         DEBUG(7,("Deleting expired krb5 credential cache\n"));
  93                         ads->is_mine = True;
  94                         ads_destroy( &ads );
  95                         ads_kdestroy(WINBIND_CCACHE_NAME);
  96                         ctx->ads = NULL;
  97                         TALLOC_FREE( ctx->ad_schema );
  98                 }
  99         }
 100 
 101         if (!local) {
 102                 /* we don't want this to affect the users ccache */
 103                 setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
 104         }
 105 
 106         /*
 107          * At this point we only have the NetBIOS domain name.
 108          * Check if we can get server nam and realm from SAF cache
 109          * and the domain list.
 110          */
 111         ldap_server = saf_fetch(dom->name);
 112         DEBUG(10, ("ldap_server from saf cache: '%s'\n", ldap_server?ldap_server:""));
 113 
 114         wb_dom = find_domain_from_name_noinit(dom->name);
 115         if (wb_dom == NULL) {
 116                 DEBUG(10, ("find_domain_from_name_noinit did not find domain '%s'\n",
 117                            dom->name));
 118                 realm = NULL;
 119         } else {
 120                 DEBUG(10, ("find_domain_from_name_noinit found realm '%s' for "
 121                           " domain '%s'\n", wb_dom->alt_name, dom->name));
 122                 realm = wb_dom->alt_name;
 123         }
 124 
 125         if ( (ads = ads_init(realm, dom->name, ldap_server)) == NULL ) {
 126                 DEBUG(1,("ads_init failed\n"));
 127                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
 128         }
 129 
 130         /* the machine acct password might have change - fetch it every time */
 131         SAFE_FREE(ads->auth.password);
 132         ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
 133 
 134         SAFE_FREE(ads->auth.realm);
 135         ads->auth.realm = SMB_STRDUP(lp_realm());
 136 
 137         /* setup server affinity */
 138 
 139         get_dc_name(dom->name, realm, dc_name, &dc_ip );
 140         
 141         status = ads_connect(ads);
 142         if (!ADS_ERR_OK(status)) {
 143                 DEBUG(1, ("ad_idmap_init: failed to connect to AD\n"));
 144                 ads_destroy(&ads);
 145                 return status;
 146         }
 147 
 148         ads->is_mine = False;
 149 
 150         ctx->ads = ads;
 151 
 152         return ADS_SUCCESS;
 153 }
 154 
 155 /************************************************************************
 156  ***********************************************************************/
 157 
 158 static ADS_STATUS ad_idmap_cached_connection(struct idmap_domain *dom)
     /* [<][>][^][v][top][bottom][index][help] */
 159 {
 160         ADS_STATUS status;
 161         struct idmap_ad_context * ctx;
 162 
 163         status = ad_idmap_cached_connection_internal(dom);
 164         if (!ADS_ERR_OK(status)) {
 165                 return status;
 166         }
 167 
 168         ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
 169 
 170         /* if we have a valid ADS_STRUCT and the schema model is
 171            defined, then we can return here. */
 172 
 173         if ( ctx->ad_schema ) {
 174                 return ADS_SUCCESS;
 175         }
 176 
 177         /* Otherwise, set the schema model */
 178 
 179         if ( (ctx->ad_map_type ==  WB_POSIX_MAP_SFU) ||
 180              (ctx->ad_map_type ==  WB_POSIX_MAP_SFU20) ||
 181              (ctx->ad_map_type ==  WB_POSIX_MAP_RFC2307) )
 182         {
 183                 status = ads_check_posix_schema_mapping(NULL, ctx->ads, ctx->ad_map_type, &ctx->ad_schema);
 184                 if ( !ADS_ERR_OK(status) ) {
 185                         DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n"));
 186                 }
 187         }
 188         
 189         return status;
 190 }
 191 
 192 /************************************************************************
 193  ***********************************************************************/
 194 
 195 static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom,
     /* [<][>][^][v][top][bottom][index][help] */
 196                                     const char *params)
 197 {
 198         struct idmap_ad_context *ctx;
 199         char *config_option;
 200         const char *range = NULL;
 201         const char *schema_mode = NULL; 
 202 
 203         if ( (ctx = TALLOC_ZERO_P(dom, struct idmap_ad_context)) == NULL ) {
 204                 DEBUG(0, ("Out of memory!\n"));
 205                 return NT_STATUS_NO_MEMORY;
 206         }
 207 
 208         if ( (config_option = talloc_asprintf(ctx, "idmap config %s", dom->name)) == NULL ) {
 209                 DEBUG(0, ("Out of memory!\n"));
 210                 talloc_free(ctx);
 211                 return NT_STATUS_NO_MEMORY;
 212         }
 213 
 214         /* load ranges */
 215         range = lp_parm_const_string(-1, config_option, "range", NULL);
 216         if (range && range[0]) {
 217                 if ((sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2) ||
 218                     (ctx->filter_low_id > ctx->filter_high_id)) {
 219                         DEBUG(1, ("ERROR: invalid filter range [%s]", range));
 220                         ctx->filter_low_id = 0;
 221                         ctx->filter_high_id = 0;
 222                 }
 223         }
 224 
 225         /* default map type */
 226         ctx->ad_map_type = WB_POSIX_MAP_RFC2307;
 227 
 228         /* schema mode */
 229         schema_mode = lp_parm_const_string(-1, config_option, "schema_mode", NULL);
 230         if ( schema_mode && schema_mode[0] ) {
 231                 if ( strequal(schema_mode, "sfu") )
 232                         ctx->ad_map_type = WB_POSIX_MAP_SFU;
 233                 else if ( strequal(schema_mode, "sfu20" ) )
 234                         ctx->ad_map_type = WB_POSIX_MAP_SFU20;
 235                 else if ( strequal(schema_mode, "rfc2307" ) )
 236                         ctx->ad_map_type = WB_POSIX_MAP_RFC2307;
 237                 else
 238                         DEBUG(0,("idmap_ad_initialize: Unknown schema_mode (%s)\n",
 239                                  schema_mode));
 240         }
 241 
 242         dom->private_data = ctx;
 243 
 244         talloc_free(config_option);
 245 
 246         return NT_STATUS_OK;
 247 }
 248 
 249 /************************************************************************
 250  Search up to IDMAP_AD_MAX_IDS entries in maps for a match.
 251  ***********************************************************************/
 252 
 253 static struct id_map *find_map_by_id(struct id_map **maps, enum id_type type, uint32_t id)
     /* [<][>][^][v][top][bottom][index][help] */
 254 {
 255         int i;
 256 
 257         for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
 258                 if ((maps[i]->xid.type == type) && (maps[i]->xid.id == id)) {
 259                         return maps[i];
 260                 }
 261         }
 262 
 263         return NULL;    
 264 }
 265 
 266 /************************************************************************
 267  Search up to IDMAP_AD_MAX_IDS entries in maps for a match
 268  ***********************************************************************/
 269 
 270 static struct id_map *find_map_by_sid(struct id_map **maps, DOM_SID *sid)
     /* [<][>][^][v][top][bottom][index][help] */
 271 {
 272         int i;
 273 
 274         for (i = 0; maps[i] && i<IDMAP_AD_MAX_IDS; i++) {
 275                 if (sid_equal(maps[i]->sid, sid)) {
 276                         return maps[i];
 277                 }
 278         }
 279 
 280         return NULL;    
 281 }
 282 
 283 /************************************************************************
 284  ***********************************************************************/
 285 
 286 static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
     /* [<][>][^][v][top][bottom][index][help] */
 287 {
 288         NTSTATUS ret;
 289         TALLOC_CTX *memctx;
 290         struct idmap_ad_context *ctx;
 291         ADS_STATUS rc;
 292         const char *attrs[] = { "sAMAccountType", 
 293                                 "objectSid",
 294                                 NULL, /* uidnumber */
 295                                 NULL, /* gidnumber */
 296                                 NULL };
 297         LDAPMessage *res = NULL;
 298         LDAPMessage *entry = NULL;
 299         char *filter = NULL;
 300         int idx = 0;
 301         int bidx = 0;
 302         int count;
 303         int i;
 304         char *u_filter = NULL;
 305         char *g_filter = NULL;
 306 
 307         /* initialize the status to avoid suprise */
 308         for (i = 0; ids[i]; i++) {
 309                 ids[i]->status = ID_UNKNOWN;
 310         }
 311         
 312         /* Only do query if we are online */
 313         if (idmap_is_offline()) {
 314                 return NT_STATUS_FILE_IS_OFFLINE;
 315         }
 316 
 317         ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
 318 
 319         if ( (memctx = talloc_new(ctx)) == NULL ) {
 320                 DEBUG(0, ("Out of memory!\n"));
 321                 return NT_STATUS_NO_MEMORY;
 322         }
 323 
 324         rc = ad_idmap_cached_connection(dom);
 325         if (!ADS_ERR_OK(rc)) {
 326                 DEBUG(1, ("ADS uninitialized: %s\n", ads_errstr(rc)));
 327                 ret = NT_STATUS_UNSUCCESSFUL;
 328                 /* ret = ads_ntstatus(rc); */
 329                 goto done;
 330         }
 331 
 332         attrs[2] = ctx->ad_schema->posix_uidnumber_attr;
 333         attrs[3] = ctx->ad_schema->posix_gidnumber_attr;
 334 
 335 again:
 336         bidx = idx;
 337         for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
 338                 switch (ids[idx]->xid.type) {
 339                 case ID_TYPE_UID:     
 340                         if ( ! u_filter) {
 341                                 u_filter = talloc_asprintf(memctx, "(&(|"
 342                                                            "(sAMAccountType=%d)"
 343                                                            "(sAMAccountType=%d)"
 344                                                            "(sAMAccountType=%d))(|",
 345                                                            ATYPE_NORMAL_ACCOUNT,
 346                                                            ATYPE_WORKSTATION_TRUST,
 347                                                            ATYPE_INTERDOMAIN_TRUST);
 348                         }
 349                         u_filter = talloc_asprintf_append_buffer(u_filter, "(%s=%lu)",
 350                                                           ctx->ad_schema->posix_uidnumber_attr,
 351                                                           (unsigned long)ids[idx]->xid.id);
 352                         CHECK_ALLOC_DONE(u_filter);
 353                         break;
 354                                 
 355                 case ID_TYPE_GID:
 356                         if ( ! g_filter) {
 357                                 g_filter = talloc_asprintf(memctx, "(&(|"
 358                                                            "(sAMAccountType=%d)"
 359                                                            "(sAMAccountType=%d))(|",
 360                                                            ATYPE_SECURITY_GLOBAL_GROUP,
 361                                                            ATYPE_SECURITY_LOCAL_GROUP);
 362                         }
 363                         g_filter = talloc_asprintf_append_buffer(g_filter, "(%s=%lu)",
 364                                                           ctx->ad_schema->posix_gidnumber_attr,
 365                                                           (unsigned long)ids[idx]->xid.id);
 366                         CHECK_ALLOC_DONE(g_filter);
 367                         break;
 368 
 369                 default:
 370                         DEBUG(3, ("Error: mapping requested but Unknown ID type\n"));
 371                         ids[idx]->status = ID_UNKNOWN;
 372                         continue;
 373                 }
 374         }
 375         filter = talloc_asprintf(memctx, "(|");
 376         CHECK_ALLOC_DONE(filter);
 377         if ( u_filter) {
 378                 filter = talloc_asprintf_append_buffer(filter, "%s))", u_filter);
 379                 CHECK_ALLOC_DONE(filter);
 380                         TALLOC_FREE(u_filter);
 381         }
 382         if ( g_filter) {
 383                 filter = talloc_asprintf_append_buffer(filter, "%s))", g_filter);
 384                 CHECK_ALLOC_DONE(filter);
 385                 TALLOC_FREE(g_filter);
 386         }
 387         filter = talloc_asprintf_append_buffer(filter, ")");
 388         CHECK_ALLOC_DONE(filter);
 389 
 390         rc = ads_search_retry(ctx->ads, &res, filter, attrs);
 391         if (!ADS_ERR_OK(rc)) {
 392                 DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc)));
 393                 ret = NT_STATUS_UNSUCCESSFUL;
 394                 goto done;
 395         }
 396 
 397         if ( (count = ads_count_replies(ctx->ads, res)) == 0 ) {
 398                 DEBUG(10, ("No IDs found\n"));
 399         }
 400 
 401         entry = res;
 402         for (i = 0; (i < count) && entry; i++) {
 403                 DOM_SID sid;
 404                 enum id_type type;
 405                 struct id_map *map;
 406                 uint32_t id;
 407                 uint32_t atype;
 408 
 409                 if (i == 0) { /* first entry */
 410                         entry = ads_first_entry(ctx->ads, entry);
 411                 } else { /* following ones */
 412                         entry = ads_next_entry(ctx->ads, entry);
 413                 }
 414 
 415                 if ( !entry ) {
 416                         DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
 417                         break;
 418                 }
 419 
 420                 /* first check if the SID is present */
 421                 if (!ads_pull_sid(ctx->ads, entry, "objectSid", &sid)) {
 422                         DEBUG(2, ("Could not retrieve SID from entry\n"));
 423                         continue;
 424                 }
 425 
 426                 /* get type */
 427                 if (!ads_pull_uint32(ctx->ads, entry, "sAMAccountType", &atype)) {
 428                         DEBUG(1, ("could not get SAM account type\n"));
 429                         continue;
 430                 }
 431 
 432                 switch (atype & 0xF0000000) {
 433                 case ATYPE_SECURITY_GLOBAL_GROUP:
 434                 case ATYPE_SECURITY_LOCAL_GROUP:
 435                         type = ID_TYPE_GID;
 436                         break;
 437                 case ATYPE_NORMAL_ACCOUNT:
 438                 case ATYPE_WORKSTATION_TRUST:
 439                 case ATYPE_INTERDOMAIN_TRUST:
 440                         type = ID_TYPE_UID;
 441                         break;
 442                 default:
 443                         DEBUG(1, ("unrecognized SAM account type %08x\n", atype));
 444                         continue;
 445                 }
 446 
 447                 if (!ads_pull_uint32(ctx->ads, entry, (type==ID_TYPE_UID) ?
 448                                                  ctx->ad_schema->posix_uidnumber_attr :
 449                                                  ctx->ad_schema->posix_gidnumber_attr,
 450                                      &id)) 
 451                 {
 452                         DEBUG(1, ("Could not get unix ID\n"));
 453                         continue;
 454                 }
 455 
 456                 if ((id == 0) ||
 457                     (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
 458                     (ctx->filter_high_id && (id > ctx->filter_high_id))) {
 459                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
 460                                 id, ctx->filter_low_id, ctx->filter_high_id));
 461                         continue;
 462                 }
 463 
 464                 map = find_map_by_id(&ids[bidx], type, id);
 465                 if (!map) {
 466                         DEBUG(2, ("WARNING: couldn't match result with requested ID\n"));
 467                         continue;
 468                 }
 469 
 470                 sid_copy(map->sid, &sid);
 471 
 472                 /* mapped */
 473                 map->status = ID_MAPPED;
 474 
 475                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
 476                            (unsigned long)map->xid.id,
 477                            map->xid.type));
 478         }
 479 
 480         if (res) {
 481                 ads_msgfree(ctx->ads, res);
 482         }
 483 
 484         if (ids[idx]) { /* still some values to map */
 485                 goto again;
 486         }
 487 
 488         ret = NT_STATUS_OK;
 489 
 490         /* mark all unknown/expired ones as unmapped */
 491         for (i = 0; ids[i]; i++) {
 492                 if (ids[i]->status != ID_MAPPED) 
 493                         ids[i]->status = ID_UNMAPPED;
 494         }
 495 
 496 done:
 497         talloc_free(memctx);
 498         return ret;
 499 }
 500 
 501 /************************************************************************
 502  ***********************************************************************/
 503 
 504 static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
     /* [<][>][^][v][top][bottom][index][help] */
 505 {
 506         NTSTATUS ret;
 507         TALLOC_CTX *memctx;
 508         struct idmap_ad_context *ctx;
 509         ADS_STATUS rc;
 510         const char *attrs[] = { "sAMAccountType", 
 511                                 "objectSid",
 512                                 NULL, /* attr_uidnumber */
 513                                 NULL, /* attr_gidnumber */
 514                                 NULL };
 515         LDAPMessage *res = NULL;
 516         LDAPMessage *entry = NULL;
 517         char *filter = NULL;
 518         int idx = 0;
 519         int bidx = 0;
 520         int count;
 521         int i;
 522         char *sidstr;
 523 
 524         /* initialize the status to avoid suprise */
 525         for (i = 0; ids[i]; i++) {
 526                 ids[i]->status = ID_UNKNOWN;
 527         }
 528 
 529         /* Only do query if we are online */
 530         if (idmap_is_offline()) {
 531                 return NT_STATUS_FILE_IS_OFFLINE;
 532         }
 533 
 534         ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);      
 535 
 536         if ( (memctx = talloc_new(ctx)) == NULL ) {             
 537                 DEBUG(0, ("Out of memory!\n"));
 538                 return NT_STATUS_NO_MEMORY;
 539         }
 540 
 541         rc = ad_idmap_cached_connection(dom);
 542         if (!ADS_ERR_OK(rc)) {
 543                 DEBUG(1, ("ADS uninitialized: %s\n", ads_errstr(rc)));
 544                 ret = NT_STATUS_UNSUCCESSFUL;
 545                 /* ret = ads_ntstatus(rc); */
 546                 goto done;
 547         }
 548 
 549         if (ctx->ad_schema == NULL) {
 550                 DEBUG(0, ("haven't got ctx->ad_schema ! \n"));
 551                 ret = NT_STATUS_UNSUCCESSFUL;
 552                 goto done;
 553         }
 554 
 555         attrs[2] = ctx->ad_schema->posix_uidnumber_attr;
 556         attrs[3] = ctx->ad_schema->posix_gidnumber_attr;
 557 
 558 again:
 559         filter = talloc_asprintf(memctx, "(&(|"
 560                                  "(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)" /* user account types */
 561                                  "(sAMAccountType=%d)(sAMAccountType=%d)" /* group account types */
 562                                  ")(|",
 563                                  ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
 564                                  ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP);
 565                 
 566         CHECK_ALLOC_DONE(filter);
 567 
 568         bidx = idx;
 569         for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
 570 
 571                 ids[idx]->status = ID_UNKNOWN;
 572 
 573                 sidstr = sid_binstring(ids[idx]->sid);
 574                 filter = talloc_asprintf_append_buffer(filter, "(objectSid=%s)", sidstr);
 575                         
 576                 free(sidstr);
 577                 CHECK_ALLOC_DONE(filter);
 578         }
 579         filter = talloc_asprintf_append_buffer(filter, "))");
 580         CHECK_ALLOC_DONE(filter);
 581         DEBUG(10, ("Filter: [%s]\n", filter));
 582 
 583         rc = ads_search_retry(ctx->ads, &res, filter, attrs);
 584         if (!ADS_ERR_OK(rc)) {
 585                 DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc)));
 586                 ret = NT_STATUS_UNSUCCESSFUL;
 587                 goto done;
 588         }
 589 
 590         if ( (count = ads_count_replies(ctx->ads, res)) == 0 ) {
 591                 DEBUG(10, ("No IDs found\n"));
 592         }
 593 
 594         entry = res;    
 595         for (i = 0; (i < count) && entry; i++) {
 596                 DOM_SID sid;
 597                 enum id_type type;
 598                 struct id_map *map;
 599                 uint32_t id;
 600                 uint32_t atype;
 601 
 602                 if (i == 0) { /* first entry */
 603                         entry = ads_first_entry(ctx->ads, entry);
 604                 } else { /* following ones */
 605                         entry = ads_next_entry(ctx->ads, entry);
 606                 }
 607 
 608                 if ( !entry ) {
 609                         DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
 610                         break;
 611                 }
 612 
 613                 /* first check if the SID is present */
 614                 if (!ads_pull_sid(ctx->ads, entry, "objectSid", &sid)) {
 615                         DEBUG(2, ("Could not retrieve SID from entry\n"));
 616                         continue;
 617                 }
 618 
 619                 map = find_map_by_sid(&ids[bidx], &sid);
 620                 if (!map) {
 621                         DEBUG(2, ("WARNING: couldn't match result with requested SID\n"));
 622                         continue;
 623                 }
 624 
 625                 /* get type */
 626                 if (!ads_pull_uint32(ctx->ads, entry, "sAMAccountType", &atype)) {
 627                         DEBUG(1, ("could not get SAM account type\n"));
 628                         continue;
 629                 }
 630 
 631                 switch (atype & 0xF0000000) {
 632                 case ATYPE_SECURITY_GLOBAL_GROUP:
 633                 case ATYPE_SECURITY_LOCAL_GROUP:
 634                         type = ID_TYPE_GID;
 635                         break;
 636                 case ATYPE_NORMAL_ACCOUNT:
 637                 case ATYPE_WORKSTATION_TRUST:
 638                 case ATYPE_INTERDOMAIN_TRUST:
 639                         type = ID_TYPE_UID;
 640                         break;
 641                 default:
 642                         DEBUG(1, ("unrecognized SAM account type %08x\n", atype));
 643                         continue;
 644                 }
 645 
 646                 if (!ads_pull_uint32(ctx->ads, entry, (type==ID_TYPE_UID) ?
 647                                                  ctx->ad_schema->posix_uidnumber_attr :
 648                                                  ctx->ad_schema->posix_gidnumber_attr,
 649                                      &id)) 
 650                 {
 651                         DEBUG(1, ("Could not get unix ID\n"));
 652                         continue;
 653                 }
 654                 if ((id == 0) ||
 655                     (ctx->filter_low_id && (id < ctx->filter_low_id)) ||
 656                     (ctx->filter_high_id && (id > ctx->filter_high_id))) {
 657                         DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
 658                                 id, ctx->filter_low_id, ctx->filter_high_id));
 659                         continue;
 660                 }
 661 
 662                 /* mapped */
 663                 map->xid.type = type;
 664                 map->xid.id = id;
 665                 map->status = ID_MAPPED;
 666 
 667                 DEBUG(10, ("Mapped %s -> %lu (%d)\n", sid_string_dbg(map->sid),
 668                            (unsigned long)map->xid.id,
 669                            map->xid.type));
 670         }
 671 
 672         if (res) {
 673                 ads_msgfree(ctx->ads, res);
 674         }
 675 
 676         if (ids[idx]) { /* still some values to map */
 677                 goto again;
 678         }
 679 
 680         ret = NT_STATUS_OK;
 681 
 682         /* mark all unknwoni/expired ones as unmapped */
 683         for (i = 0; ids[i]; i++) {
 684                 if (ids[i]->status != ID_MAPPED) 
 685                         ids[i]->status = ID_UNMAPPED;
 686         }
 687 
 688 done:
 689         talloc_free(memctx);
 690         return ret;
 691 }
 692 
 693 /************************************************************************
 694  ***********************************************************************/
 695 
 696 static NTSTATUS idmap_ad_close(struct idmap_domain *dom)
     /* [<][>][^][v][top][bottom][index][help] */
 697 {
 698         struct idmap_ad_context * ctx;
 699 
 700         ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
 701 
 702         if (ctx->ads != NULL) {
 703                 /* we own this ADS_STRUCT so make sure it goes away */
 704                 ctx->ads->is_mine = True;
 705                 ads_destroy( &ctx->ads );
 706                 ctx->ads = NULL;
 707         }
 708 
 709         TALLOC_FREE( ctx->ad_schema );
 710         
 711         return NT_STATUS_OK;
 712 }
 713 
 714 /*
 715  * nss_info_{sfu,sfu20,rfc2307}
 716  */
 717 
 718 /************************************************************************
 719  Initialize the {sfu,sfu20,rfc2307} state
 720  ***********************************************************************/
 721 
 722 static const char *wb_posix_map_unknown_string = "WB_POSIX_MAP_UNKNOWN";
 723 static const char *wb_posix_map_template_string = "WB_POSIX_MAP_TEMPLATE";
 724 static const char *wb_posix_map_sfu_string = "WB_POSIX_MAP_SFU";
 725 static const char *wb_posix_map_sfu20_string = "WB_POSIX_MAP_SFU20";
 726 static const char *wb_posix_map_rfc2307_string = "WB_POSIX_MAP_RFC2307";
 727 static const char *wb_posix_map_unixinfo_string = "WB_POSIX_MAP_UNIXINFO";
 728 
 729 static const char *ad_map_type_string(enum wb_posix_mapping map_type)
     /* [<][>][^][v][top][bottom][index][help] */
 730 {
 731         switch (map_type) {
 732                 case WB_POSIX_MAP_TEMPLATE:
 733                         return wb_posix_map_template_string;
 734                 case WB_POSIX_MAP_SFU:
 735                         return wb_posix_map_sfu_string;
 736                 case WB_POSIX_MAP_SFU20:
 737                         return wb_posix_map_sfu20_string;
 738                 case WB_POSIX_MAP_RFC2307:
 739                         return wb_posix_map_rfc2307_string;
 740                 case WB_POSIX_MAP_UNIXINFO:
 741                         return wb_posix_map_unixinfo_string;
 742                 default:
 743                         return wb_posix_map_unknown_string;
 744         }
 745 }
 746 
 747 static NTSTATUS nss_ad_generic_init(struct nss_domain_entry *e,
     /* [<][>][^][v][top][bottom][index][help] */
 748                                     enum wb_posix_mapping new_ad_map_type)
 749 {
 750         struct idmap_domain *dom;
 751         struct idmap_ad_context *ctx;
 752 
 753         if (e->state != NULL) {
 754                 dom = talloc_get_type(e->state, struct idmap_domain);
 755         } else {
 756                 dom = TALLOC_ZERO_P(e, struct idmap_domain);
 757                 if (dom == NULL) {
 758                         DEBUG(0, ("Out of memory!\n"));
 759                         return NT_STATUS_NO_MEMORY;
 760                 }
 761                 e->state = dom;
 762         }
 763 
 764         if (e->domain != NULL) {
 765                 dom->name = talloc_strdup(dom, e->domain);
 766                 if (dom->name == NULL) {
 767                         DEBUG(0, ("Out of memory!\n"));
 768                         return NT_STATUS_NO_MEMORY;
 769                 }
 770         }
 771 
 772         if (dom->private_data != NULL) {
 773                 ctx = talloc_get_type(dom->private_data,
 774                                       struct idmap_ad_context);
 775         } else {
 776                 ctx = TALLOC_ZERO_P(dom, struct idmap_ad_context);
 777                 if (ctx == NULL) {
 778                         DEBUG(0, ("Out of memory!\n"));
 779                         return NT_STATUS_NO_MEMORY;
 780                 }
 781                 ctx->ad_map_type = WB_POSIX_MAP_RFC2307;
 782                 dom->private_data = ctx;
 783         }
 784 
 785         if ((ctx->ad_map_type != WB_POSIX_MAP_UNKNOWN) &&
 786             (ctx->ad_map_type != new_ad_map_type))
 787         {
 788                 DEBUG(2, ("nss_ad_generic_init: "
 789                           "Warning: overriding previously set posix map type "
 790                           "%s for domain %s with map type %s.\n",
 791                           ad_map_type_string(ctx->ad_map_type),
 792                           dom->name,
 793                           ad_map_type_string(new_ad_map_type)));
 794         }
 795 
 796         ctx->ad_map_type = new_ad_map_type;
 797 
 798         return NT_STATUS_OK;
 799 }
 800 
 801 static NTSTATUS nss_sfu_init( struct nss_domain_entry *e )
     /* [<][>][^][v][top][bottom][index][help] */
 802 {
 803         return nss_ad_generic_init(e, WB_POSIX_MAP_SFU);
 804 }
 805 
 806 static NTSTATUS nss_sfu20_init( struct nss_domain_entry *e )
     /* [<][>][^][v][top][bottom][index][help] */
 807 {
 808         return nss_ad_generic_init(e, WB_POSIX_MAP_SFU20);
 809 }
 810 
 811 static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e )
     /* [<][>][^][v][top][bottom][index][help] */
 812 {
 813         return nss_ad_generic_init(e, WB_POSIX_MAP_RFC2307);
 814 }
 815 
 816 
 817 /************************************************************************
 818  ***********************************************************************/
 819 
 820 static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e, 
     /* [<][>][^][v][top][bottom][index][help] */
 821                                   const DOM_SID *sid, 
 822                                   TALLOC_CTX *mem_ctx,
 823                                   ADS_STRUCT *ads, 
 824                                   LDAPMessage *msg,
 825                                   char **homedir,
 826                                   char **shell, 
 827                                   char **gecos,
 828                                   uint32 *gid )
 829 {
 830         const char *attrs[] = {NULL, /* attr_homedir */
 831                                NULL, /* attr_shell */
 832                                NULL, /* attr_gecos */
 833                                NULL, /* attr_gidnumber */
 834                                NULL };
 835         char *filter = NULL;
 836         LDAPMessage *msg_internal = NULL;
 837         ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
 838         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 839         char *sidstr = NULL;
 840         struct idmap_domain *dom;
 841         struct idmap_ad_context *ctx;
 842 
 843         DEBUG(10, ("nss_ad_get_info called for sid [%s] in domain '%s'\n",
 844                    sid_string_dbg(sid), e->domain?e->domain:"NULL"));
 845 
 846         /* Only do query if we are online */
 847         if (idmap_is_offline()) {
 848                 return NT_STATUS_FILE_IS_OFFLINE;
 849         }
 850 
 851         dom = talloc_get_type(e->state, struct idmap_domain);
 852         ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
 853 
 854         ads_status = ad_idmap_cached_connection(dom);
 855         if (!ADS_ERR_OK(ads_status)) {
 856                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 857         }
 858 
 859         if (!ctx->ad_schema) {
 860                 DEBUG(10, ("nss_ad_get_info: no ad_schema configured!\n"));
 861                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 862         }
 863 
 864         if (!sid || !homedir || !shell || !gecos) {
 865                 return NT_STATUS_INVALID_PARAMETER;
 866         }
 867 
 868         /* See if we can use the ADS connection struct swe were given */
 869 
 870         if (ads) {
 871                 DEBUG(10, ("nss_ad_get_info: using given ads connection and "
 872                            "LDAP message (%p)\n", msg));
 873 
 874                 *homedir = ads_pull_string( ads, mem_ctx, msg, ctx->ad_schema->posix_homedir_attr );
 875                 *shell   = ads_pull_string( ads, mem_ctx, msg, ctx->ad_schema->posix_shell_attr );
 876                 *gecos   = ads_pull_string( ads, mem_ctx, msg, ctx->ad_schema->posix_gecos_attr );
 877 
 878                 if (gid) {
 879                         if ( !ads_pull_uint32(ads, msg, ctx->ad_schema->posix_gidnumber_attr, gid ) )
 880                                 *gid = (uint32)-1;
 881                 }
 882 
 883                 nt_status = NT_STATUS_OK;
 884                 goto done;
 885         }
 886 
 887         /* Have to do our own query */
 888 
 889         DEBUG(10, ("nss_ad_get_info: no ads connection given, doing our "
 890                    "own query\n"));
 891 
 892         attrs[0] = ctx->ad_schema->posix_homedir_attr;
 893         attrs[1] = ctx->ad_schema->posix_shell_attr;
 894         attrs[2] = ctx->ad_schema->posix_gecos_attr;
 895         attrs[3] = ctx->ad_schema->posix_gidnumber_attr;
 896 
 897         sidstr = sid_binstring(sid);
 898         filter = talloc_asprintf(mem_ctx, "(objectSid=%s)", sidstr);
 899         SAFE_FREE(sidstr);
 900 
 901         if (!filter) {
 902                 nt_status = NT_STATUS_NO_MEMORY;
 903                 goto done;
 904         }
 905 
 906         ads_status = ads_search_retry(ctx->ads, &msg_internal, filter, attrs);
 907         if (!ADS_ERR_OK(ads_status)) {
 908                 nt_status = ads_ntstatus(ads_status);
 909                 goto done;
 910         }
 911 
 912         *homedir = ads_pull_string(ctx->ads, mem_ctx, msg_internal, ctx->ad_schema->posix_homedir_attr);
 913         *shell   = ads_pull_string(ctx->ads, mem_ctx, msg_internal, ctx->ad_schema->posix_shell_attr);
 914         *gecos   = ads_pull_string(ctx->ads, mem_ctx, msg_internal, ctx->ad_schema->posix_gecos_attr);
 915 
 916         if (gid) {
 917                 if (!ads_pull_uint32(ctx->ads, msg_internal, ctx->ad_schema->posix_gidnumber_attr, gid))
 918                         *gid = (uint32)-1;
 919         }
 920 
 921         nt_status = NT_STATUS_OK;
 922 
 923 done:
 924         if (msg_internal) {
 925                 ads_msgfree(ctx->ads, msg_internal);
 926         }
 927 
 928         return nt_status;
 929 }
 930 
 931 /**********************************************************************
 932  *********************************************************************/
 933 
 934 static NTSTATUS nss_ad_map_to_alias(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 935                                     struct nss_domain_entry *e,
 936                                     const char *name,
 937                                     char **alias)
 938 {
 939         const char *attrs[] = {NULL, /* attr_uid */
 940                                NULL };
 941         char *filter = NULL;
 942         LDAPMessage *msg = NULL;
 943         ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
 944         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 945         struct idmap_domain *dom;
 946         struct idmap_ad_context *ctx = NULL;
 947 
 948         /* Check incoming parameters */
 949 
 950         if ( !e || !e->domain || !name || !*alias) {
 951                 nt_status = NT_STATUS_INVALID_PARAMETER;
 952                 goto done;
 953         }
 954 
 955         /* Only do query if we are online */
 956 
 957         if (idmap_is_offline()) {
 958                 nt_status = NT_STATUS_FILE_IS_OFFLINE;
 959                 goto done;
 960         }
 961 
 962         dom = talloc_get_type(e->state, struct idmap_domain);
 963         ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
 964 
 965         ads_status = ad_idmap_cached_connection(dom);
 966         if (!ADS_ERR_OK(ads_status)) {
 967                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 968         }
 969 
 970         if (!ctx->ad_schema) {
 971                 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
 972                 goto done;
 973         }
 974 
 975         attrs[0] = ctx->ad_schema->posix_uid_attr;
 976 
 977         filter = talloc_asprintf(mem_ctx,
 978                                  "(sAMAccountName=%s)",
 979                                  name);
 980         if (!filter) {
 981                 nt_status = NT_STATUS_NO_MEMORY;
 982                 goto done;
 983         }
 984 
 985         ads_status = ads_search_retry(ctx->ads, &msg, filter, attrs);
 986         if (!ADS_ERR_OK(ads_status)) {
 987                 nt_status = ads_ntstatus(ads_status);
 988                 goto done;
 989         }
 990 
 991         *alias = ads_pull_string(ctx->ads, mem_ctx, msg, ctx->ad_schema->posix_uid_attr);
 992 
 993         if (!*alias) {
 994                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 995         }
 996 
 997         nt_status = NT_STATUS_OK;
 998 
 999 done:
1000         if (filter) {
1001                 talloc_destroy(filter);
1002         }
1003         if (msg) {
1004                 ads_msgfree(ctx->ads, msg);
1005         }
1006 
1007         return nt_status;
1008 }
1009 
1010 /**********************************************************************
1011  *********************************************************************/
1012 
1013 static NTSTATUS nss_ad_map_from_alias( TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1014                                              struct nss_domain_entry *e,
1015                                              const char *alias,
1016                                              char **name )
1017 {
1018         const char *attrs[] = {"sAMAccountName",
1019                                NULL };
1020         char *filter = NULL;
1021         LDAPMessage *msg = NULL;
1022         ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
1023         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1024         char *username;
1025         struct idmap_domain *dom;
1026         struct idmap_ad_context *ctx = NULL;
1027 
1028         /* Check incoming parameters */
1029 
1030         if ( !alias || !name) {
1031                 nt_status = NT_STATUS_INVALID_PARAMETER;
1032                 goto done;
1033         }
1034 
1035         /* Only do query if we are online */
1036 
1037         if (idmap_is_offline()) {
1038                 nt_status = NT_STATUS_FILE_IS_OFFLINE;
1039                 goto done;
1040         }
1041 
1042         dom = talloc_get_type(e->state, struct idmap_domain);
1043         ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
1044 
1045         ads_status = ad_idmap_cached_connection(dom);
1046         if (!ADS_ERR_OK(ads_status)) {
1047                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1048         }
1049 
1050         if (!ctx->ad_schema) {
1051                 nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
1052                 goto done;
1053         }
1054 
1055         filter = talloc_asprintf(mem_ctx,
1056                                  "(%s=%s)",
1057                                  ctx->ad_schema->posix_uid_attr,
1058                                  alias);
1059         if (!filter) {
1060                 nt_status = NT_STATUS_NO_MEMORY;
1061                 goto done;
1062         }
1063 
1064         ads_status = ads_search_retry(ctx->ads, &msg, filter, attrs);
1065         if (!ADS_ERR_OK(ads_status)) {
1066                 nt_status = ads_ntstatus(ads_status);
1067                 goto done;
1068         }
1069 
1070         username = ads_pull_string(ctx->ads, mem_ctx, msg,
1071                                    "sAMAccountName");
1072         if (!username) {
1073                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1074         }
1075 
1076         *name = talloc_asprintf(mem_ctx, "%s\\%s",
1077                                 lp_workgroup(),
1078                                 username);
1079         if (!*name) {
1080                 nt_status = NT_STATUS_NO_MEMORY;
1081                 goto done;
1082         }
1083 
1084         nt_status = NT_STATUS_OK;
1085 
1086 done:
1087         if (filter) {
1088                 talloc_destroy(filter);
1089         }
1090         if (msg) {
1091                 ads_msgfree(ctx->ads, msg);
1092         }
1093 
1094         return nt_status;
1095 }
1096 
1097 
1098 /************************************************************************
1099  ***********************************************************************/
1100 
1101 static NTSTATUS nss_ad_close( void )
     /* [<][>][^][v][top][bottom][index][help] */
1102 {
1103         /* nothing to do.  All memory is free()'d by the idmap close_fn() */
1104 
1105         return NT_STATUS_OK;
1106 }
1107 
1108 /************************************************************************
1109  Function dispatch tables for the idmap and nss plugins
1110  ***********************************************************************/
1111 
1112 static struct idmap_methods ad_methods = {
1113         .init            = idmap_ad_initialize,
1114         .unixids_to_sids = idmap_ad_unixids_to_sids,
1115         .sids_to_unixids = idmap_ad_sids_to_unixids,
1116         .close_fn        = idmap_ad_close
1117 };
1118 
1119 /* The SFU and RFC2307 NSS plugins share everything but the init
1120    function which sets the intended schema model to use */
1121   
1122 static struct nss_info_methods nss_rfc2307_methods = {
1123         .init           = nss_rfc2307_init,
1124         .get_nss_info   = nss_ad_get_info,
1125         .map_to_alias   = nss_ad_map_to_alias,
1126         .map_from_alias = nss_ad_map_from_alias,
1127         .close_fn       = nss_ad_close
1128 };
1129 
1130 static struct nss_info_methods nss_sfu_methods = {
1131         .init           = nss_sfu_init,
1132         .get_nss_info   = nss_ad_get_info,
1133         .map_to_alias   = nss_ad_map_to_alias,
1134         .map_from_alias = nss_ad_map_from_alias,
1135         .close_fn       = nss_ad_close
1136 };
1137 
1138 static struct nss_info_methods nss_sfu20_methods = {
1139         .init           = nss_sfu20_init,
1140         .get_nss_info   = nss_ad_get_info,
1141         .map_to_alias   = nss_ad_map_to_alias,
1142         .map_from_alias = nss_ad_map_from_alias,
1143         .close_fn       = nss_ad_close
1144 };
1145 
1146 
1147 
1148 /************************************************************************
1149  Initialize the plugins
1150  ***********************************************************************/
1151 
1152 NTSTATUS idmap_ad_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
1153 {
1154         static NTSTATUS status_idmap_ad = NT_STATUS_UNSUCCESSFUL;
1155         static NTSTATUS status_nss_rfc2307 = NT_STATUS_UNSUCCESSFUL;
1156         static NTSTATUS status_nss_sfu = NT_STATUS_UNSUCCESSFUL;
1157         static NTSTATUS status_nss_sfu20 = NT_STATUS_UNSUCCESSFUL;
1158 
1159         /* Always register the AD method first in order to get the
1160            idmap_domain interface called */
1161 
1162         if ( !NT_STATUS_IS_OK(status_idmap_ad) ) {
1163                 status_idmap_ad = smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, 
1164                                                      "ad", &ad_methods);
1165                 if ( !NT_STATUS_IS_OK(status_idmap_ad) )
1166                         return status_idmap_ad;         
1167         }
1168         
1169         if ( !NT_STATUS_IS_OK( status_nss_rfc2307 ) ) {
1170                 status_nss_rfc2307 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
1171                                                             "rfc2307",  &nss_rfc2307_methods );         
1172                 if ( !NT_STATUS_IS_OK(status_nss_rfc2307) )
1173                         return status_nss_rfc2307;
1174         }
1175 
1176         if ( !NT_STATUS_IS_OK( status_nss_sfu ) ) {
1177                 status_nss_sfu = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
1178                                                         "sfu",  &nss_sfu_methods );             
1179                 if ( !NT_STATUS_IS_OK(status_nss_sfu) )
1180                         return status_nss_sfu;          
1181         }
1182 
1183         if ( !NT_STATUS_IS_OK( status_nss_sfu20 ) ) {
1184                 status_nss_sfu20 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
1185                                                         "sfu20",  &nss_sfu20_methods );         
1186                 if ( !NT_STATUS_IS_OK(status_nss_sfu20) )
1187                         return status_nss_sfu20;                
1188         }
1189 
1190         return NT_STATUS_OK;    
1191 }
1192 

/* [<][>][^][v][top][bottom][index][help] */