r23801: The FSF has moved around a lot. This fixes their Mass Ave address.
[bbaumbach/samba-autobuild/.git] / source3 / nsswitch / idmap_ad.c
index fee53a0539ed7c00c01a079365bc1c6e2fd763e4..6f8839e4ba37144b08b791b1e55c3bfa5d7e3ec3 100644 (file)
@@ -12,7 +12,7 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -21,8 +21,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "includes.h"
@@ -143,6 +142,7 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
        /* Otherwise, set the schema model */
 
        if ( (ad_map_type ==  WB_POSIX_MAP_SFU) ||
+            (ad_map_type ==  WB_POSIX_MAP_SFU20) || 
             (ad_map_type ==  WB_POSIX_MAP_RFC2307) ) 
        {
                ADS_STATUS schema_status;
@@ -160,19 +160,14 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
 /************************************************************************
  ***********************************************************************/
 
-static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, const char *params)
+static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom)
 {
        struct idmap_ad_context *ctx;
        char *config_option;
-       const char *range;
-       ADS_STRUCT *ads;
-
-       /* verify AD is reachable (not critical, we may just be offline at start) */
-       if ( (ads = ad_idmap_cached_connection()) == NULL ) {
-               DEBUG(1, ("WARNING: Could not init an AD connection! Mapping might not work.\n"));
-       }
+       const char *range = NULL;
+       const char *schema_mode = NULL; 
 
-       if ( (ctx = talloc_zero(dom, struct idmap_ad_context)) == NULL ) {
+       if ( (ctx = TALLOC_ZERO_P(dom, struct idmap_ad_context)) == NULL ) {
                DEBUG(0, ("Out of memory!\n"));
                return NT_STATUS_NO_MEMORY;
        }
@@ -194,27 +189,24 @@ static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom, const char *params
                }
        }
 
-       /* idmap AD can work well only if it is the default module (trusts)
-        * with additional BUILTIN and alloc using TDB */
-       if ( ! dom->default_domain) {
-               DEBUG(1, ("WARNING: idmap_ad is not configured as the default domain.\n"
-                         "For best results we suggest you to configure this module as\n"
-                         "default and configure BULTIN to use idmap_tdb\n"
-                         "ex: idmap domains = BUILTIN %s\n"
-                         "    idmap alloc config: range = 5000 - 9999\n"
-                         "    idmap config %s: default = yes\n"
-                         "    idmap config %s: backend = ad\n"
-                         "    idmap config %s: range = 10000 - 10000000  #this is optional\n"
-                         "NOTE: make sure the ranges do not overlap\n",
-                         dom->name, dom->name, dom->name, dom->name));
-       }
-
-       if ( !dom->readonly ) {
-               DEBUG(1, ("WARNING: forcing to readonly, as idmap_ad can't write on AD.\n"));
-               dom->readonly = true;
+       /* schema mode */
+       if ( ad_map_type == WB_POSIX_MAP_UNKNOWN )
+               ad_map_type = WB_POSIX_MAP_RFC2307;
+       schema_mode = lp_parm_const_string(-1, config_option, "schema_mode", NULL);
+       if ( schema_mode && schema_mode[0] ) {
+               if ( strequal(schema_mode, "sfu") )
+                       ad_map_type = WB_POSIX_MAP_SFU;
+               else if ( strequal(schema_mode, "sfu20" ) )
+                       ad_map_type = WB_POSIX_MAP_SFU20;
+               else if ( strequal(schema_mode, "rfc2307" ) )
+                       ad_map_type = WB_POSIX_MAP_RFC2307;
+               else
+                       DEBUG(0,("idmap_ad_initialize: Unknown schema_mode (%s)\n",
+                                schema_mode));
        }
 
        dom->private_data = ctx;
+       dom->initialized = True;
 
        talloc_free(config_option);
 
@@ -271,6 +263,7 @@ static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map
                                NULL, /* gidnumber */
                                NULL };
        LDAPMessage *res = NULL;
+       LDAPMessage *entry = NULL;
        char *filter = NULL;
        int idx = 0;
        int bidx = 0;
@@ -279,6 +272,19 @@ static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map
        char *u_filter = NULL;
        char *g_filter = NULL;
 
+       /* Only do query if we are online */
+       if (idmap_is_offline()) {
+               return NT_STATUS_FILE_IS_OFFLINE;
+       }
+
+       /* Initilization my have been deferred because we were offline */
+       if ( ! dom->initialized) {
+               ret = idmap_ad_initialize(dom);
+               if ( ! NT_STATUS_IS_OK(ret)) {
+                       return ret;
+               }
+       }
+
        ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);
 
        if ( (memctx = talloc_new(ctx)) == NULL ) {
@@ -330,7 +336,7 @@ again:
                        break;
 
                default:
-                       DEBUG(3, ("Unknown ID type\n"));
+                       DEBUG(3, ("Error: mapping requested but Unknown ID type\n"));
                        ids[idx]->status = ID_UNKNOWN;
                        continue;
                }
@@ -349,7 +355,7 @@ again:
        }
        filter = talloc_asprintf_append(filter, ")");
        CHECK_ALLOC_DONE(filter);
-       DEBUG(10, ("Filter: [%s]\n", filter));
+
        rc = ads_search_retry(ads, &res, filter, attrs);
        if (!ADS_ERR_OK(rc)) {
                DEBUG(1, ("ERROR: ads search returned: %s\n", ads_errstr(rc)));
@@ -361,8 +367,8 @@ again:
                DEBUG(10, ("No IDs found\n"));
        }
 
-       for (i = 0; i < count; i++) {
-               LDAPMessage *entry = NULL;
+       entry = res;
+       for (i = 0; (i < count) && entry; i++) {
                DOM_SID sid;
                enum id_type type;
                struct id_map *map;
@@ -370,13 +376,14 @@ again:
                uint32_t atype;
 
                if (i == 0) { /* first entry */
-                       entry = ads_first_entry(ads, res);
+                       entry = ads_first_entry(ads, entry);
                } else { /* following ones */
                        entry = ads_next_entry(ads, entry);
                }
-               if ( ! entry) {
+
+               if ( !entry ) {
                        DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
-                       continue;
+                       break;
                }
 
                /* first check if the SID is present */
@@ -450,9 +457,9 @@ again:
 
        ret = NT_STATUS_OK;
 
-       /* mark all unknown ones as unmapped */
+       /* mark all unknown/expired ones as unmapped */
        for (i = 0; ids[i]; i++) {
-               if (ids[i]->status == ID_UNKNOWN
+               if (ids[i]->status != ID_MAPPED
                        ids[i]->status = ID_UNMAPPED;
        }
 
@@ -477,6 +484,7 @@ static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map
                                NULL, /* attr_gidnumber */
                                NULL };
        LDAPMessage *res = NULL;
+       LDAPMessage *entry = NULL;
        char *filter = NULL;
        int idx = 0;
        int bidx = 0;
@@ -484,6 +492,19 @@ static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map
        int i;
        char *sidstr;
 
+       /* Only do query if we are online */
+       if (idmap_is_offline()) {
+               return NT_STATUS_FILE_IS_OFFLINE;
+       }
+
+       /* Initilization my have been deferred because we were offline */
+       if ( ! dom->initialized) {
+               ret = idmap_ad_initialize(dom);
+               if ( ! NT_STATUS_IS_OK(ret)) {
+                       return ret;
+               }
+       }
+
        ctx = talloc_get_type(dom->private_data, struct idmap_ad_context);      
 
        if ( (memctx = talloc_new(ctx)) == NULL ) {             
@@ -534,8 +555,8 @@ again:
                DEBUG(10, ("No IDs found\n"));
        }
 
-       for (i = 0; i < count; i++) {
-               LDAPMessage *entry = NULL;
+       entry = res;    
+       for (i = 0; (i < count) && entry; i++) {
                DOM_SID sid;
                enum id_type type;
                struct id_map *map;
@@ -543,13 +564,14 @@ again:
                uint32_t atype;
 
                if (i == 0) { /* first entry */
-                       entry = ads_first_entry(ads, res);
+                       entry = ads_first_entry(ads, entry);
                } else { /* following ones */
                        entry = ads_next_entry(ads, entry);
                }
-               if ( ! entry) {
+
+               if ( !entry ) {
                        DEBUG(2, ("ERROR: Unable to fetch ldap entries from results\n"));
-                       continue;
+                       break;
                }
 
                /* first check if the SID is present */
@@ -622,9 +644,9 @@ again:
 
        ret = NT_STATUS_OK;
 
-       /* mark all unknwon ones as unmapped */
+       /* mark all unknwoni/expired ones as unmapped */
        for (i = 0; ids[i]; i++) {
-               if (ids[i]->status == ID_UNKNOWN
+               if (ids[i]->status != ID_MAPPED
                        ids[i]->status = ID_UNMAPPED;
        }
 
@@ -653,11 +675,11 @@ static NTSTATUS idmap_ad_close(struct idmap_domain *dom)
 }
 
 /*
- * nss_info_{sfu,rfc2307}
+ * nss_info_{sfu,sfu20,rfc2307}
  */
 
 /************************************************************************
- Initialize the {sfu,rfc2307} state
+ Initialize the {sfu,sfu20,rfc2307} state
  ***********************************************************************/
 
 static NTSTATUS nss_sfu_init( struct nss_domain_entry *e )
@@ -673,10 +695,25 @@ static NTSTATUS nss_sfu_init( struct nss_domain_entry *e )
                return NT_STATUS_NOT_SUPPORTED;
        }
        
-       ad_map_type =  WB_POSIX_MAP_SFU;        
+       ad_map_type = WB_POSIX_MAP_SFU; 
 
-       if ( !ad_idmap_ads ) 
-               return idmap_ad_initialize( NULL, NULL );       
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS nss_sfu20_init( struct nss_domain_entry *e )
+{
+       /* Sanity check if we have previously been called with a
+          different schema model */
+
+       if ( (ad_map_type != WB_POSIX_MAP_UNKNOWN) &&
+            (ad_map_type != WB_POSIX_MAP_SFU20) )
+       {
+               DEBUG(0,("nss_sfu20_init: Posix Map type has already been set.  "
+                        "Mixed schema models not supported!\n"));
+               return NT_STATUS_NOT_SUPPORTED;
+       }
+       
+       ad_map_type = WB_POSIX_MAP_SFU20;       
 
        return NT_STATUS_OK;
 }
@@ -694,10 +731,7 @@ static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e )
                return NT_STATUS_NOT_SUPPORTED;
        }
        
-       ad_map_type =  WB_POSIX_MAP_RFC2307;
-
-       if ( !ad_idmap_ads ) 
-               return idmap_ad_initialize( NULL, NULL );       
+       ad_map_type = WB_POSIX_MAP_RFC2307;
 
        return NT_STATUS_OK;
 }
@@ -717,6 +751,11 @@ static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e,
 {
        ADS_STRUCT *ads_internal = NULL;
 
+       /* Only do query if we are online */
+       if (idmap_is_offline()) {
+               return NT_STATUS_FILE_IS_OFFLINE;
+       }
+
        /* We are assuming that the internal ADS_STRUCT is for the 
           same forest as the incoming *ads pointer */
 
@@ -776,6 +815,13 @@ static struct nss_info_methods nss_sfu_methods = {
        .close_fn     = nss_ad_close
 };
 
+static struct nss_info_methods nss_sfu20_methods = {
+       .init         = nss_sfu20_init,
+       .get_nss_info = nss_ad_get_info,
+       .close_fn     = nss_ad_close
+};
+
+
 
 /************************************************************************
  Initialize the plugins
@@ -786,6 +832,7 @@ NTSTATUS idmap_ad_init(void)
        static NTSTATUS status_idmap_ad = NT_STATUS_UNSUCCESSFUL;
        static NTSTATUS status_nss_rfc2307 = NT_STATUS_UNSUCCESSFUL;
        static NTSTATUS status_nss_sfu = NT_STATUS_UNSUCCESSFUL;
+       static NTSTATUS status_nss_sfu20 = NT_STATUS_UNSUCCESSFUL;
 
        /* Always register the AD method first in order to get the
           idmap_domain interface called */
@@ -811,6 +858,13 @@ NTSTATUS idmap_ad_init(void)
                        return status_nss_sfu;          
        }
 
+       if ( !NT_STATUS_IS_OK( status_nss_sfu20 ) ) {
+               status_nss_sfu20 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
+                                                       "sfu20",  &nss_sfu20_methods );         
+               if ( !NT_STATUS_IS_OK(status_nss_sfu20) )
+                       return status_nss_sfu20;                
+       }
+
        return NT_STATUS_OK;    
 }