s3:winbindd/idmap_ad: rename ctx to mem_ctx in nss_ad_get_info()
[ira/wip.git] / source3 / winbindd / idmap_ad.c
index b99da57a4a72e6e3b58258a85ca4b6a55c1cfe9c..170c1d954e3096c42fd9439c2059afbbdead8069 100644 (file)
@@ -77,15 +77,15 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void)
 
                if ( ads->config.realm && (expire > time(NULL))) {
                        return ads;
+               } else {
+                       /* we own this ADS_STRUCT so make sure it goes away */
+                       DEBUG(7,("Deleting expired krb5 credential cache\n"));
+                       ads->is_mine = True;
+                       ads_destroy( &ads );
+                       ads_kdestroy(WINBIND_CCACHE_NAME);
+                       ad_idmap_ads = NULL;
+                       TALLOC_FREE( ad_schema );                       
                }
-
-               /* we own this ADS_STRUCT so make sure it goes away */
-               DEBUG(7,("Deleting expired krb5 credential cache\n"));
-               ads->is_mine = True;
-               ads_destroy( &ads );
-               ads_kdestroy(WINBIND_CCACHE_NAME);
-               ad_idmap_ads = NULL;
-               TALLOC_FREE( ad_schema );
        }
 
        if (!local) {
@@ -108,7 +108,7 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void)
        /* setup server affinity */
 
        get_dc_name( NULL, ads->auth.realm, dc_name, &dc_ip );
-
+       
        status = ads_connect(ads);
        if (!ADS_ERR_OK(status)) {
                DEBUG(1, ("ad_idmap_init: failed to connect to AD\n"));
@@ -129,7 +129,7 @@ static ADS_STRUCT *ad_idmap_cached_connection_internal(void)
 static ADS_STRUCT *ad_idmap_cached_connection(void)
 {
        ADS_STRUCT *ads = ad_idmap_cached_connection_internal();
-
+       
        if ( !ads )
                return NULL;
 
@@ -146,21 +146,22 @@ static ADS_STRUCT *ad_idmap_cached_connection(void)
             (ad_map_type ==  WB_POSIX_MAP_RFC2307) ) 
        {
                ADS_STATUS schema_status;
-
+               
                schema_status = ads_check_posix_schema_mapping( NULL, ads, ad_map_type, &ad_schema);
                if ( !ADS_ERR_OK(schema_status) ) {
                        DEBUG(2,("ad_idmap_cached_connection: Failed to obtain schema details!\n"));
                        return NULL;                    
                }
        }
-
+       
        return ads;
 }
 
 /************************************************************************
  ***********************************************************************/
 
-static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom)
+static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom,
+                                   const char *params)
 {
        struct idmap_ad_context *ctx;
        char *config_option;
@@ -206,7 +207,6 @@ static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom)
        }
 
        dom->private_data = ctx;
-       dom->initialized = True;
 
        talloc_free(config_option);
 
@@ -277,14 +277,6 @@ static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom, struct id_map
                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 ) {
@@ -320,7 +312,7 @@ again:
                                                          (unsigned long)ids[idx]->xid.id);
                        CHECK_ALLOC_DONE(u_filter);
                        break;
-
+                               
                case ID_TYPE_GID:
                        if ( ! g_filter) {
                                g_filter = talloc_asprintf(memctx, "(&(|"
@@ -496,14 +488,6 @@ static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom, struct id_map
                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 ) {             
@@ -527,15 +511,17 @@ again:
                                 ")(|",
                                 ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST, ATYPE_INTERDOMAIN_TRUST,
                                 ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP);
-
+               
        CHECK_ALLOC_DONE(filter);
 
        bidx = idx;
        for (i = 0; (i < IDMAP_AD_MAX_IDS) && ids[idx]; i++, idx++) {
 
+               ids[idx]->status = ID_UNKNOWN;
+
                sidstr = sid_binstring(ids[idx]->sid);
                filter = talloc_asprintf_append_buffer(filter, "(objectSid=%s)", sidstr);
-
+                       
                free(sidstr);
                CHECK_ALLOC_DONE(filter);
        }
@@ -668,7 +654,7 @@ static NTSTATUS idmap_ad_close(struct idmap_domain *dom)
        }
 
        TALLOC_FREE( ad_schema );
-
+       
        return NT_STATUS_OK;
 }
 
@@ -692,7 +678,7 @@ static NTSTATUS nss_sfu_init( struct nss_domain_entry *e )
                         "Mixed schema models not supported!\n"));
                return NT_STATUS_NOT_SUPPORTED;
        }
-
+       
        ad_map_type = WB_POSIX_MAP_SFU; 
 
        return NT_STATUS_OK;
@@ -710,7 +696,7 @@ static NTSTATUS nss_sfu20_init( struct nss_domain_entry *e )
                         "Mixed schema models not supported!\n"));
                return NT_STATUS_NOT_SUPPORTED;
        }
-
+       
        ad_map_type = WB_POSIX_MAP_SFU20;       
 
        return NT_STATUS_OK;
@@ -720,7 +706,7 @@ static NTSTATUS nss_rfc2307_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_RFC2307) ) 
        {
@@ -728,7 +714,7 @@ static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e )
                         "Mixed schema models not supported!\n"));
                return NT_STATUS_NOT_SUPPORTED;
        }
-
+       
        ad_map_type = WB_POSIX_MAP_RFC2307;
 
        return NT_STATUS_OK;
@@ -739,7 +725,7 @@ static NTSTATUS nss_rfc2307_init( struct nss_domain_entry *e )
  ***********************************************************************/
 static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e, 
                                  const DOM_SID *sid, 
-                                 TALLOC_CTX *ctx,
+                                 TALLOC_CTX *mem_ctx,
                                  ADS_STRUCT *ads, 
                                  LDAPMessage *msg,
                                  char **homedir,
@@ -748,6 +734,16 @@ static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e,
                                  uint32 *gid )
 {
        ADS_STRUCT *ads_internal = NULL;
+       const char *attrs[] = {NULL, /* attr_homedir */
+                              NULL, /* attr_shell */
+                              NULL, /* attr_gecos */
+                              NULL, /* attr_gidnumber */
+                              NULL };
+       char *filter = NULL;
+       LDAPMessage *msg_internal = NULL;
+       ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+       NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+       char *sidstr = NULL;
 
        /* Only do query if we are online */
        if (idmap_is_offline()) {
@@ -759,24 +755,224 @@ static NTSTATUS nss_ad_get_info( struct nss_domain_entry *e,
 
        ads_internal = ad_idmap_cached_connection();
 
-       if ( !ads_internal || !ad_schema )
+       if ( !ads_internal || !ad_schema ) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
 
-       if ( !homedir || !shell || !gecos )
+       if (!sid || !homedir || !shell || !gecos) {
                return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* See if we can use the ADS connection struct swe were given */
+
+       if (ads) {
+               *homedir = ads_pull_string( ads, mem_ctx, msg, ad_schema->posix_homedir_attr );
+               *shell   = ads_pull_string( ads, mem_ctx, msg, ad_schema->posix_shell_attr );
+               *gecos   = ads_pull_string( ads, mem_ctx, msg, ad_schema->posix_gecos_attr );
 
-       *homedir = ads_pull_string( ads, ctx, msg, ad_schema->posix_homedir_attr );
-       *shell   = ads_pull_string( ads, ctx, msg, ad_schema->posix_shell_attr );
-       *gecos   = ads_pull_string( ads, ctx, msg, ad_schema->posix_gecos_attr );
+               if (gid) {
+                       if ( !ads_pull_uint32(ads, msg, ad_schema->posix_gidnumber_attr, gid ) )
+                               *gid = (uint32)-1;
+               }
 
-       if ( gid ) {            
-               if ( !ads_pull_uint32(ads, msg, ad_schema->posix_gidnumber_attr, gid ) )
-                       *gid = (uint32)-1;              
+               nt_status = NT_STATUS_OK;
+               goto done;
        }
 
-       return NT_STATUS_OK;
+       /* Have to do our own query */
+
+       attrs[0] = ad_schema->posix_homedir_attr;
+       attrs[1] = ad_schema->posix_shell_attr;
+       attrs[2] = ad_schema->posix_gecos_attr;
+       attrs[3] = ad_schema->posix_gidnumber_attr;
+
+       sidstr = sid_binstring(sid);
+       filter = talloc_asprintf(mem_ctx, "(objectSid=%s)", sidstr);
+       SAFE_FREE(sidstr);
+
+       if (!filter) {
+               nt_status = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       ads_status = ads_search_retry(ads_internal, &msg_internal, filter, attrs);
+       if (!ADS_ERR_OK(ads_status)) {
+               nt_status = ads_ntstatus(ads_status);
+               goto done;
+       }
+
+       *homedir = ads_pull_string(ads_internal, mem_ctx, msg_internal, ad_schema->posix_homedir_attr);
+       *shell   = ads_pull_string(ads_internal, mem_ctx, msg_internal, ad_schema->posix_shell_attr);
+       *gecos   = ads_pull_string(ads_internal, mem_ctx, msg_internal, ad_schema->posix_gecos_attr);
+
+       if (gid) {
+               if (!ads_pull_uint32(ads_internal, msg_internal, ad_schema->posix_gidnumber_attr, gid))
+                       *gid = (uint32)-1;
+       }
+
+       nt_status = NT_STATUS_OK;
+
+done:
+       if (msg_internal) {
+               ads_msgfree(ads_internal, msg_internal);
+       }
+
+       return nt_status;
 }
 
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS nss_ad_map_to_alias(TALLOC_CTX *mem_ctx,
+                                   struct nss_domain_entry *e,
+                                   const char *name,
+                                   char **alias)
+{
+       ADS_STRUCT *ads_internal = NULL;
+       const char *attrs[] = {NULL, /* attr_uid */
+                              NULL };
+       char *filter = NULL;
+       LDAPMessage *msg = NULL;
+       ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+       NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+
+       /* Check incoming parameters */
+
+       if ( !e || !e->domain || !name || !*alias) {
+               nt_status = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
+
+       /* Only do query if we are online */
+
+       if (idmap_is_offline()) {
+               nt_status = NT_STATUS_FILE_IS_OFFLINE;
+               goto done;
+       }
+
+       ads_internal = ad_idmap_cached_connection();
+
+       if (!ads_internal || !ad_schema) {
+               nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+               goto done;
+       }
+
+       attrs[0] = ad_schema->posix_uid_attr;
+
+       filter = talloc_asprintf(mem_ctx,
+                                "(sAMAccountName=%s)",
+                                name);
+       if (!filter) {
+               nt_status = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       ads_status = ads_search_retry(ads_internal, &msg, filter, attrs);
+       if (!ADS_ERR_OK(ads_status)) {
+               nt_status = ads_ntstatus(ads_status);
+               goto done;
+       }
+
+       *alias = ads_pull_string(ads_internal, mem_ctx, msg, ad_schema->posix_uid_attr );
+
+       if (!*alias) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       nt_status = NT_STATUS_OK;
+
+done:
+       if (filter) {
+               talloc_destroy(filter);
+       }
+       if (msg) {
+               ads_msgfree(ads_internal, msg);
+       }
+
+       return nt_status;
+}
+
+/**********************************************************************
+ *********************************************************************/
+
+static NTSTATUS nss_ad_map_from_alias( TALLOC_CTX *mem_ctx,
+                                            struct nss_domain_entry *e,
+                                            const char *alias,
+                                            char **name )
+{
+       ADS_STRUCT *ads_internal = NULL;
+       const char *attrs[] = {"sAMAccountName",
+                              NULL };
+       char *filter = NULL;
+       LDAPMessage *msg = NULL;
+       ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+       NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+       char *username;
+
+       /* Check incoming parameters */
+
+       if ( !alias || !name) {
+               nt_status = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
+
+       /* Only do query if we are online */
+
+       if (idmap_is_offline()) {
+               nt_status = NT_STATUS_FILE_IS_OFFLINE;
+               goto done;
+       }
+
+       ads_internal = ad_idmap_cached_connection();
+
+       if (!ads_internal || !ad_schema) {
+               nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+               goto done;
+       }
+
+       filter = talloc_asprintf(mem_ctx,
+                                "(%s=%s)",
+                                ad_schema->posix_uid_attr,
+                                alias);
+       if (!filter) {
+               nt_status = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       ads_status = ads_search_retry(ads_internal, &msg, filter, attrs);
+       if (!ADS_ERR_OK(ads_status)) {
+               nt_status = ads_ntstatus(ads_status);
+               goto done;
+       }
+
+       username = ads_pull_string(ads_internal, mem_ctx, msg,
+                                  "sAMAccountName");
+       if (!username) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       *name = talloc_asprintf(mem_ctx, "%s\\%s",
+                               lp_workgroup(),
+                               username);
+       if (!*name) {
+               nt_status = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       nt_status = NT_STATUS_OK;
+
+done:
+       if (filter) {
+               talloc_destroy(filter);
+       }
+       if (msg) {
+               ads_msgfree(ads_internal, msg);
+       }
+
+       return nt_status;
+}
+
+
 /************************************************************************
  ***********************************************************************/
 
@@ -800,23 +996,29 @@ static struct idmap_methods ad_methods = {
 
 /* The SFU and RFC2307 NSS plugins share everything but the init
    function which sets the intended schema model to use */
-
+  
 static struct nss_info_methods nss_rfc2307_methods = {
-       .init         = nss_rfc2307_init,
-       .get_nss_info = nss_ad_get_info,
-       .close_fn     = nss_ad_close
+       .init           = nss_rfc2307_init,
+       .get_nss_info   = nss_ad_get_info,
+       .map_to_alias   = nss_ad_map_to_alias,
+       .map_from_alias = nss_ad_map_from_alias,
+       .close_fn       = nss_ad_close
 };
 
 static struct nss_info_methods nss_sfu_methods = {
-       .init         = nss_sfu_init,
-       .get_nss_info = nss_ad_get_info,
-       .close_fn     = nss_ad_close
+       .init           = nss_sfu_init,
+       .get_nss_info   = nss_ad_get_info,
+       .map_to_alias   = nss_ad_map_to_alias,
+       .map_from_alias = nss_ad_map_from_alias,
+       .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
+       .init           = nss_sfu20_init,
+       .get_nss_info   = nss_ad_get_info,
+       .map_to_alias   = nss_ad_map_to_alias,
+       .map_from_alias = nss_ad_map_from_alias,
+       .close_fn       = nss_ad_close
 };
 
 
@@ -841,7 +1043,7 @@ NTSTATUS idmap_ad_init(void)
                if ( !NT_STATUS_IS_OK(status_idmap_ad) )
                        return status_idmap_ad;         
        }
-
+       
        if ( !NT_STATUS_IS_OK( status_nss_rfc2307 ) ) {
                status_nss_rfc2307 = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
                                                            "rfc2307",  &nss_rfc2307_methods );