first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[nivanova/samba-autobuild/.git] / source3 / lib / sids.c
index c75168ee56617d41caee218f98f6b48875cb8369..712eef8a0dfe6bb47dac6f8220abab23bb0d7f65 100644 (file)
@@ -69,13 +69,14 @@ DOM_SID global_sid_S_1_1;    /* everyone */
 DOM_SID global_sid_S_1_3;    /* Creator Owner */
 DOM_SID global_sid_S_1_5;    /* NT Authority */
 
-static struct sid_name_map_info
+struct sid_map
 {
        DOM_SID *sid;
        char *name;
 
-}
-sid_name_map[] =
+};
+
+struct sid_map static_sid_name_map[] =
 {
        { &global_sid_S_1_5_20, "BUILTIN" },
        { &global_sid_S_1_1   , "Everyone" },
@@ -86,39 +87,65 @@ sid_name_map[] =
        { NULL                , NULL      }
 };
 
-/****************************************************************************
- Read the machine SID from a file.
-****************************************************************************/
-
-static BOOL read_sid_from_file(int fd, char *sid_file)
-{   
-  fstring fline;
-       fstring sid_str;
-    
-  memset(fline, '\0', sizeof(fline));
-
-  if (read(fd, fline, sizeof(fline) -1 ) < 0) {
-    DEBUG(0,("unable to read file %s. Error was %s\n",
-           sid_file, strerror(errno) ));
-    return False;
-  }
+struct sid_map **sid_name_map = NULL;
+uint32 num_maps = 0;
 
-  /*
-   * Convert to the machine SID.
-   */
-
-  fline[sizeof(fline)-1] = '\0';
-  if (!string_to_sid( &global_sam_sid, fline)) {
-    DEBUG(0,("unable to generate machine SID.\n"));
-    return False;
-  }
+static struct sid_map *sid_map_dup(const struct sid_map *from)
+{
+       if (from != NULL)
+       {
+               struct sid_map *copy = (struct sid_map *)
+                                       malloc(sizeof(struct sid_map));
+               if (copy != NULL)
+               {
+                       ZERO_STRUCTP(copy);
+                       if (from->name != NULL)
+                       {
+                               copy->name  = strdup(from->name );
+                       }
+                       if (from->sid != NULL)
+                       {
+                               copy->sid = sid_dup(from->sid);
+                       }
+               }
+               return copy;
+       }
+       return NULL;
+}
 
-       sid_to_string(sid_str, &global_sam_sid);
-       DEBUG(5,("read_sid_from_file: sid %s\n", sid_str));
+static void sid_map_free(struct sid_map *map)
+{
+       if (map->name != NULL)
+       {
+               free(map->name);
+       }
+       if (map->sid != NULL)
+       {
+               free(map->sid);
+       }
+       free(map);
+}
 
-  return True;
+/****************************************************************************
+free a sid map array
+****************************************************************************/
+static void free_sidmap_array(uint32 num_entries, struct sid_map **entries)
+{
+       void(*fn)(void*) = (void(*)(void*))&sid_map_free;
+       free_void_array(num_entries, (void**)entries, *fn);
 }
 
+/****************************************************************************
+add a sid map state to the array
+****************************************************************************/
+struct sid_map* add_sidmap_to_array(uint32 *len, struct sid_map ***array,
+                               const struct sid_map *name)
+{
+       void*(*fn)(const void*) = (void*(*)(const void*))&sid_map_dup;
+       return (struct sid_map*)add_copy_to_array(len,
+                            (void***)array, (const void*)name, *fn, False);
+                               
+}
 /****************************************************************************
  sets up the name associated with the SAM database for which we are responsible
 ****************************************************************************/
@@ -172,129 +199,79 @@ BOOL get_member_domain_sid(void)
                }
        }
 
-       return get_domain_sids(NULL, &global_member_sid, lp_passwordserver());
+       return get_domain_sids(lp_workgroup(), NULL, &global_member_sid);
 }
 
+
 /****************************************************************************
- obtain the sid from the PDC.  do some verification along the way...
+ creates some useful well known sids
 ****************************************************************************/
-BOOL get_domain_sids(DOM_SID *sid3, DOM_SID *sid5, char *servers)
+void generate_wellknown_sids(void)
 {
-       uint16 nt_pipe_fnum;
-       POLICY_HND pol;
-       fstring srv_name;
-       struct cli_state cli;
-       BOOL res = True;
-       fstring dom3;
-       fstring dom5;
-
-       if (sid3 == NULL && sid5 == NULL)
-       {
-               /* don't waste my time... */
-               return False;
-       }
-
-       if (!cli_connect_serverlist(&cli, servers))
-       {
-               DEBUG(0,("get_domain_sids: unable to initialise client connection.\n"));
-               return False;
-       }
+       string_to_sid(&global_sid_S_1_5_20, "S-1-5-32");
+       string_to_sid(&global_sid_S_1_1   , "S-1-1"   );
+       string_to_sid(&global_sid_S_1_3   , "S-1-3"   );
+       string_to_sid(&global_sid_S_1_5   , "S-1-5"   );
+}
 
-       /*
-        * Ok - we have an anonymous connection to the IPC$ share.
-        * Now start the NT Domain stuff :-).
-        */
+/****************************************************************************
+ create a sid map table
+****************************************************************************/
+BOOL create_sidmap_table(void)
+{
+       int i;
+       char **doms = NULL;
+       uint32 num_doms = 0;
 
-       fstrcpy(dom3, "");
-       fstrcpy(dom5, "");
-       if (sid3 != NULL)
-       {
-               ZERO_STRUCTP(sid3);
-       }
-       if (sid5 != NULL)
+       for (i = 0; static_sid_name_map[i].name != NULL; i++)
        {
-               ZERO_STRUCTP(sid5);
+               add_sidmap_to_array(&num_maps, &sid_name_map,
+                                   &static_sid_name_map[i]);
        }
 
-       fstrcpy(srv_name, "\\\\");
-       fstrcat(srv_name, global_myname);
-       strupper(srv_name);
+       enumtrustdoms(&doms, &num_doms);
 
-       /* open LSARPC session. */
-       res = res ? cli_nt_session_open(&cli, PIPE_LSARPC, &nt_pipe_fnum) : False;
-
-       /* lookup domain controller; receive a policy handle */
-       res = res ? lsa_open_policy(&cli, nt_pipe_fnum, srv_name, &pol, False) : False;
-
-       if (sid3 != NULL)
+       for (i = 0; i < num_doms; i++)
        {
-               /* send client info query, level 3.  receive domain name and sid */
-               res = res ? lsa_query_info_pol(&cli, nt_pipe_fnum, &pol, 3, dom3, sid3) : False;
-       }
+               struct sid_map map;
+               DOM_SID sid;
 
-       if (sid5 != NULL)
-       {
-               /* send client info query, level 5.  receive domain name and sid */
-               res = res ? lsa_query_info_pol(&cli, nt_pipe_fnum, &pol, 5, dom5, sid5) : False;
-       }
-
-       /* close policy handle */
-       res = res ? lsa_close(&cli, nt_pipe_fnum, &pol) : False;
-
-       /* close the session */
-       cli_nt_session_close(&cli, nt_pipe_fnum);
-       cli_ulogoff(&cli);
-       cli_shutdown(&cli);
+               map.name = doms[i];
+               map.sid  = &sid;
 
-       if (res)
-       {
-               pstring sid;
-               DEBUG(2,("LSA Query Info Policy\n"));
-               if (sid3 != NULL)
+               if (!read_sid(map.name, map.sid))
                {
-                       sid_to_string(sid, sid3);
-                       DEBUG(2,("Domain Member     - Domain: %s SID: %s\n", dom3, sid));
-               }
-               if (sid5 != NULL)
-               {
-                       sid_to_string(sid, sid5);
-                       DEBUG(2,("Domain Controller - Domain: %s SID: %s\n", dom5, sid));
+                       DEBUG(0,("Could not read Domain SID %s\n", map.name));
+                       return False;
                }
+               add_sidmap_to_array(&num_maps, &sid_name_map, &map);
        }
-       else
+
+
+       for (i = 0; i < num_maps; i++)
        {
-               DEBUG(1,("lsa query info failed\n"));
+               fstring sidstr;
+               sid_to_string(sidstr, sid_name_map[i]->sid);
+               DEBUG(10,("Map:\tDomain:\t%s\tSID:\t%s\n",
+                        sid_name_map[i]->name, sidstr));
        }
 
-       return res;
-}
 
-/****************************************************************************
- creates some useful well known sids
-****************************************************************************/
-void generate_wellknown_sids(void)
-{
-       string_to_sid(&global_sid_S_1_5_20, "S-1-5-32");
-       string_to_sid(&global_sid_S_1_1   , "S-1-1"   );
-       string_to_sid(&global_sid_S_1_3   , "S-1-3"   );
-       string_to_sid(&global_sid_S_1_5   , "S-1-5"   );
+       free_char_array(num_doms, doms);
+
+       return True;
 }
 
 /****************************************************************************
  Generate the global machine sid. Look for the DOMAINNAME.SID file first, if
  not found then look in smb.conf and use it to create the DOMAINNAME.SID file.
 ****************************************************************************/
-BOOL generate_sam_sid(char *domain_name)
+BOOL generate_sam_sid(char *domain_name, DOM_SID *sid)
 {
-       int fd;
-       int i;
        char *p;
        pstring sid_file;
        pstring machine_sid_file;
-       fstring sid_string;
        fstring file_name;
-       SMB_STRUCT_STAT st;
-       uchar raw_sid_data[12];
 
        pstrcpy(sid_file, lp_smb_passwd_file());
 
@@ -341,131 +318,30 @@ BOOL generate_sam_sid(char *domain_name)
                }
        }
        
-       if ((fd = sys_open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
-               DEBUG(0,("unable to open or create file %s. Error was %s\n",
-                        sid_file, strerror(errno) ));
-               return False;
-       } 
-  
-       /*
-        * Check if the file contains data.
-        */
-       
-       if (sys_fstat( fd, &st) < 0) {
-               DEBUG(0,("unable to stat file %s. Error was %s\n",
-                        sid_file, strerror(errno) ));
-               close(fd);
-               return False;
-       } 
-  
-       if (st.st_size > 0) {
-               /*
-                * We have a valid SID - read it.
-                */
-               if (!read_sid_from_file( fd, sid_file)) {
-                       DEBUG(0,("unable to read file %s. Error was %s\n",
-                                sid_file, strerror(errno) ));
-                       close(fd);
-                       return False;
-               }
-               close(fd);
+       /* attempt to read the SID from the file */
+       if (read_sid(domain_name, sid))
+       {
                return True;
-       } 
-  
-       /*
-        * Generate the new sid data & turn it into a string.
-        */
-       generate_random_buffer( raw_sid_data, 12, True);
-               
-       fstrcpy( sid_string, "S-1-5-21");
-       for( i = 0; i < 3; i++) {
-               fstring tmp_string;
-               slprintf( tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4));
-               fstrcat( sid_string, tmp_string);
        }
-       
-       fstrcat(sid_string, "\n");
-       
-       /*
-        * Ensure our new SID is valid.
-        */
-       
-       if (!string_to_sid( &global_sam_sid, sid_string)) {
-               DEBUG(0,("unable to generate machine SID.\n"));
-               return False;
-       } 
   
-       /*
-        * Do an exclusive blocking lock on the file.
-        */
-       
-       if (!do_file_lock( fd, 60, F_WRLCK)) {
-               DEBUG(0,("unable to lock file %s. Error was %s\n",
-                        sid_file, strerror(errno) ));
-               close(fd);
-               return False;
-       } 
-  
-       /*
-        * At this point we have a blocking lock on the SID
-        * file - check if in the meantime someone else wrote
-        * SID data into the file. If so - they were here first,
-        * use their data.
-        */
-       
-       if (sys_fstat( fd, &st) < 0) {
-               DEBUG(0,("unable to stat file %s. Error was %s\n",
-                        sid_file, strerror(errno) ));
-               close(fd);
+       if (!create_new_sid(sid))
+       {
                return False;
-       } 
+       }
+       /* attempt to read the SID from the file */
+       if (!write_sid(domain_name, sid))
+       {
+               return True;
+       }
   
-       if (st.st_size > 0) {
-               /*
-                * Unlock as soon as possible to reduce
-                * contention on the exclusive lock.
-                */ 
-               do_file_lock( fd, 60, F_UNLCK);
-               
-               /*
-                * We have a valid SID - read it.
-                */
-               
-               if (!read_sid_from_file( fd, sid_file)) {
-                       DEBUG(0,("unable to read file %s. Error was %s\n",
-                                sid_file, strerror(errno) ));
-                       close(fd);
-                       return False;
-               }
-               close(fd);
+       /* during the attempt to write, someone else wrote? */
+
+       /* attempt to read the SID from the file */
+       if (read_sid(domain_name, sid))
+       {
                return True;
-       } 
-       
-       /*
-        * The file is still empty and we have an exlusive lock on it.
-        * Write out out SID data into the file.
-        */
-       
-       if (fchmod(fd, 0644) < 0) {
-               DEBUG(0,("unable to set correct permissions on file %s. \
-Error was %s\n", sid_file, strerror(errno) ));
-               close(fd);
-               return False;
-       } 
-       
-       if (write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
-               DEBUG(0,("unable to write file %s. Error was %s\n",
-                        sid_file, strerror(errno) ));
-               close(fd);
-               return False;
-       } 
-       
-       /*
-        * Unlock & exit.
-        */
-       
-       do_file_lock( fd, 60, F_UNLCK);
-       close(fd);
+       }
+  
        return True;
 }   
 
@@ -506,18 +382,17 @@ BOOL map_domain_name_to_sid(DOM_SID *sid, char **nt_domain)
 
        DEBUG(5,("map_domain_name_to_sid: %s\n", (*nt_domain)));
 
-       while (sid_name_map[i].name != NULL)
+       for (i = 0; sid_name_map[i]->name != NULL; i++)
        {
-               DEBUG(5,("compare: %s\n", sid_name_map[i].name));
-               if (strequal(sid_name_map[i].name, (*nt_domain)))
+               DEBUG(5,("compare: %s\n", sid_name_map[i]->name));
+               if (strequal(sid_name_map[i]->name, (*nt_domain)))
                {
                        fstring sid_str;
-                       sid_copy(sid, sid_name_map[i].sid);
-                       sid_to_string(sid_str, sid_name_map[i].sid);
+                       sid_copy(sid, sid_name_map[i]->sid);
+                       sid_to_string(sid_str, sid_name_map[i]->sid);
                        DEBUG(5,("found %s\n", sid_str));
                        return True;
                }
-               i++;
        }
 
        DEBUG(0,("map_domain_name_to_sid: mapping to %s NOT IMPLEMENTED\n",
@@ -542,23 +417,36 @@ BOOL map_domain_sid_to_name(DOM_SID *sid, char *nt_domain)
                return False;
        }
 
-       while (sid_name_map[i].sid != NULL)
+       for (i = 0; sid_name_map[i]->sid != NULL; i++)
        {
-               sid_to_string(sid_str, sid_name_map[i].sid);
+               sid_to_string(sid_str, sid_name_map[i]->sid);
                DEBUG(5,("compare: %s\n", sid_str));
-               if (sid_equal(sid_name_map[i].sid, sid))
+               if (sid_equal(sid_name_map[i]->sid, sid))
                {
-                       fstrcpy(nt_domain, sid_name_map[i].name);
+                       fstrcpy(nt_domain, sid_name_map[i]->name);
                        DEBUG(5,("found %s\n", nt_domain));
                        return True;
                }
-               i++;
        }
 
        DEBUG(0,("map_domain_sid_to_name: mapping NOT IMPLEMENTED\n"));
 
        return False;
 }
+/**************************************************************************
+ turns a domain SID into a domain controller name.
+***************************************************************************/
+BOOL map_domain_sid_to_any_dc(DOM_SID *sid, char *dc_name)
+{
+       fstring domain;
+
+       if (!map_domain_sid_to_name(sid, domain))
+       {
+               return False;
+       }
+
+       return get_any_dc_name(domain, dc_name);
+}
 
 /**************************************************************************
  splits a name of format \DOMAIN\name or name into its two components.
@@ -596,3 +484,40 @@ BOOL split_domain_name(const char *fullname, char *domain, char *name)
        DEBUG(10,("name '%s' split into domain:%s and nt name:%s'\n", fullname, domain, name));
        return True;
 }
+
+/**************************************************************************
+ enumerates all trusted domains
+***************************************************************************/
+BOOL enumtrustdoms(char ***doms, uint32 *num_entries)
+{
+       fstring tmp;
+       char *tok;
+
+       /* add trusted domains */
+
+       tok = lp_trusted_domains();
+       if (next_token(&tok, tmp, NULL, sizeof(tmp)))
+       {
+               do
+               {
+                       fstring domain;
+                       split_at_first_component(tmp, domain, '=', NULL);
+                       add_chars_to_array(num_entries, doms, domain);
+
+               } while (next_token(NULL, tmp, NULL, sizeof(tmp)));
+       }
+
+       return True;
+}
+
+/**************************************************************************
+ enumerates all domains for which the SAM server is responsible
+***************************************************************************/
+BOOL enumdomains(char ***doms, uint32 *num_entries)
+{
+       add_chars_to_array(num_entries, doms, global_sam_name);
+       add_chars_to_array(num_entries, doms, "Builtin");
+
+       return True;
+}
+