Make use of ZERO_STRUCT instead of memset in namequery.c
[jra/samba/.git] / source / libsmb / namequery.c
index dde758b41cb44af1cb9789a599432b1b0cd07477..893c9265fd241b07a21fadbb406fe968b08a9964 100644 (file)
@@ -39,7 +39,7 @@ static char *saf_key(const char *domain)
 {
        char *keystr;
 
-       asprintf( &keystr, SAFKEY_FMT, strupper_static(domain) );
+       asprintf_strupper_m(&keystr, SAFKEY_FMT, domain);
 
        return keystr;
 }
@@ -783,20 +783,25 @@ XFILE *startlmhosts(const char *fname)
  Parse the next line in the lmhosts file.
 *********************************************************/
 
-bool getlmhostsent(XFILE *fp, pstring name, int *name_type,
+bool getlmhostsent(TALLOC_CTX *ctx, XFILE *fp, char **pp_name, int *name_type,
                struct sockaddr_storage *pss)
 {
-       pstring line;
+       char line[1024];
+
+       *pp_name = NULL;
 
        while(!x_feof(fp) && !x_ferror(fp)) {
-               pstring ip,flags,extra;
+               char *ip = NULL;
+               char *flags = NULL;
+               char *extra = NULL;
+               char *name = NULL;
                const char *ptr;
-               char *ptr1;
+               char *ptr1 = NULL;
                int count = 0;
 
                *name_type = -1;
 
-               if (!fgets_slash(line,sizeof(pstring),fp)) {
+               if (!fgets_slash(line,sizeof(line),fp)) {
                        continue;
                }
 
@@ -804,19 +809,15 @@ bool getlmhostsent(XFILE *fp, pstring name, int *name_type,
                        continue;
                }
 
-               pstrcpy(ip,"");
-               pstrcpy(name,"");
-               pstrcpy(flags,"");
-
                ptr = line;
 
-               if (next_token(&ptr,ip   ,NULL,sizeof(ip)))
+               if (next_token_talloc(ctx, &ptr, &ip, NULL))
                        ++count;
-               if (next_token(&ptr,name ,NULL, sizeof(pstring)))
+               if (next_token_talloc(ctx, &ptr, &name, NULL))
                        ++count;
-               if (next_token(&ptr,flags,NULL, sizeof(flags)))
+               if (next_token_talloc(ctx, &ptr, &flags, NULL))
                        ++count;
-               if (next_token(&ptr,extra,NULL, sizeof(extra)))
+               if (next_token_talloc(ctx, &ptr, &extra, NULL))
                        ++count;
 
                if (count <= 0)
@@ -834,6 +835,13 @@ bool getlmhostsent(XFILE *fp, pstring name, int *name_type,
                        continue;
                }
 
+               if (!flags) {
+                       flags = talloc_strdup(ctx, "");
+                       if (!flags) {
+                               continue;
+                       }
+               }
+
                DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n",
                                        ip, name, flags));
 
@@ -864,6 +872,10 @@ bool getlmhostsent(XFILE *fp, pstring name, int *name_type,
                        *(--ptr1) = '\0'; /* Truncate at the '#' */
                }
 
+               *pp_name = talloc_strdup(ctx, name);
+               if (!*pp_name) {
+                       return false;
+               }
                return true;
        }
 
@@ -1039,6 +1051,7 @@ NTSTATUS resolve_wins(const char *name,
                DEBUG(3,("resolve_wins: cannot receive WINS replies "
                        "on IPv6 address %s\n",
                        addr));
+               wins_srv_tags_free(wins_tags);
                return NT_STATUS_INVALID_PARAMETER;
        }
 
@@ -1135,10 +1148,11 @@ static NTSTATUS resolve_lmhosts(const char *name, int name_type,
         */
 
        XFILE *fp;
-       pstring lmhost_name;
+       char *lmhost_name = NULL;
        int name_type2;
        struct sockaddr_storage return_ss;
        NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+       TALLOC_CTX *ctx = NULL;
 
        *return_iplist = NULL;
        *return_count = 0;
@@ -1147,24 +1161,35 @@ static NTSTATUS resolve_lmhosts(const char *name, int name_type,
                "Attempting lmhosts lookup for name %s<0x%x>\n",
                name, name_type));
 
-       fp = startlmhosts(dyn_LMHOSTSFILE);
+       fp = startlmhosts(get_dyn_LMHOSTSFILE());
 
        if ( fp == NULL )
                return NT_STATUS_NO_SUCH_FILE;
 
-       while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ss)) {
+       ctx = talloc_init("resolve_lmhosts");
+       if (!ctx) {
+               endlmhosts(fp);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       while (getlmhostsent(ctx, fp, &lmhost_name, &name_type2, &return_ss)) {
 
-               if (!strequal(name, lmhost_name))
+               if (!strequal(name, lmhost_name)) {
+                       TALLOC_FREE(lmhost_name);
                        continue;
+               }
 
-               if ((name_type2 != -1) && (name_type != name_type2))
+               if ((name_type2 != -1) && (name_type != name_type2)) {
+                       TALLOC_FREE(lmhost_name);
                        continue;
+               }
 
                *return_iplist = SMB_REALLOC_ARRAY((*return_iplist),
                                        struct ip_service,
                                        (*return_count)+1);
 
                if ((*return_iplist) == NULL) {
+                       TALLOC_FREE(ctx);
                        endlmhosts(fp);
                        DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
                        return NT_STATUS_NO_MEMORY;
@@ -1182,6 +1207,7 @@ static NTSTATUS resolve_lmhosts(const char *name, int name_type,
                        break;
        }
 
+       TALLOC_FREE(ctx);
        endlmhosts(fp);
        return status;
 }
@@ -1222,6 +1248,11 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_ADDRCONFIG;
 
+#if !defined(HAVE_IPV6)
+       /* Unless we have IPv6, we really only want IPv4 addresses back. */
+       hints.ai_family = AF_INET;
+#endif
+
        ret = getaddrinfo(name,
                        NULL,
                        &hints,
@@ -1239,7 +1270,7 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
                        continue;
                }
 
-               memset(&ss, '\0', sizeof(ss));
+               ZERO_STRUCT(ss);
                memcpy(&ss, res->ai_addr, res->ai_addrlen);
 
                *return_count += 1;
@@ -1269,11 +1300,11 @@ static NTSTATUS resolve_hosts(const char *name, int name_type,
  Resolve via "ADS" method.
 *********************************************************/
 
-NTSTATUS resolve_ads(const char *name,
-                       int name_type,
-                       const char *sitename,
-                       struct ip_service **return_iplist,
-                       int *return_count)
+static NTSTATUS resolve_ads(const char *name,
+                           int name_type,
+                           const char *sitename,
+                           struct ip_service **return_iplist,
+                           int *return_count)
 {
        int                     i, j;
        NTSTATUS                status;
@@ -1392,18 +1423,18 @@ NTSTATUS resolve_ads(const char *name,
  resolve_hosts() when looking up DC's via SRV RR entries in DNS
 **********************************************************************/
 
-NTSTATUS internal_resolve_name(const char *name,
+static NTSTATUS internal_resolve_name(const char *name,
                                int name_type,
                                const char *sitename,
                                struct ip_service **return_iplist,
                                int *return_count,
                                const char *resolve_order)
 {
-       pstring name_resolve_list;
-       fstring tok;
+       char *tok;
        const char *ptr;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
        int i;
+       TALLOC_CTX *frame = NULL;
 
        *return_iplist = NULL;
        *return_count = 0;
@@ -1452,21 +1483,16 @@ NTSTATUS internal_resolve_name(const char *name,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (!resolve_order) {
-               pstrcpy(name_resolve_list, lp_name_resolve_order());
-       } else {
-               pstrcpy(name_resolve_list, resolve_order);
-       }
-
-       if (!name_resolve_list[0]) {
+       if (!resolve_order[0]) {
                ptr = "host";
        } else {
-               ptr = name_resolve_list;
+               ptr = resolve_order;
        }
 
        /* iterate through the name resolution backends */
 
-       while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
+       frame = talloc_stackframe();
+       while (next_token_talloc(frame, &ptr, &tok, LIST_SEP)) {
                if((strequal(tok, "host") || strequal(tok, "hosts"))) {
                        status = resolve_hosts(name, name_type, return_iplist,
                                               return_count);
@@ -1523,6 +1549,7 @@ NTSTATUS internal_resolve_name(const char *name,
 
        /* All of the resolve_* functions above have returned false. */
 
+       TALLOC_FREE(frame);
        SAFE_FREE(*return_iplist);
        *return_count = 0;
 
@@ -1573,6 +1600,7 @@ NTSTATUS internal_resolve_name(const char *name,
                DEBUG(10, ("\n"));
        }
 
+       TALLOC_FREE(frame);
        return status;
 }
 
@@ -1619,6 +1647,87 @@ bool resolve_name(const char *name,
        return False;
 }
 
+/********************************************************
+ Internal interface to resolve a name into a list of IP addresses.
+ Use this function if the string is either an IP address, DNS
+ or host name or NetBIOS name. This uses the name switch in the
+ smb.conf to determine the order of name resolution.
+*********************************************************/
+
+NTSTATUS resolve_name_list(TALLOC_CTX *ctx,
+               const char *name,
+               int name_type,
+               struct sockaddr_storage **return_ss_arr,
+               unsigned int *p_num_entries)
+{
+       struct ip_service *ss_list = NULL;
+       char *sitename = NULL;
+       int count = 0;
+       int i;
+       unsigned int num_entries;
+       NTSTATUS status;
+
+       *p_num_entries = 0;
+       *return_ss_arr = NULL;
+
+       if (is_ipaddress(name)) {
+               *return_ss_arr = TALLOC_P(ctx, struct sockaddr_storage);
+               if (!*return_ss_arr) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               if (!interpret_string_addr(*return_ss_arr, name, AI_NUMERICHOST)) {
+                       TALLOC_FREE(*return_ss_arr);
+                       return NT_STATUS_BAD_NETWORK_NAME;
+               }
+               *p_num_entries = 1;
+               return NT_STATUS_OK;
+       }
+
+       sitename = sitename_fetch(lp_realm()); /* wild guess */
+
+       status = internal_resolve_name(name, name_type, sitename,
+                                                 &ss_list, &count,
+                                                 lp_name_resolve_order());
+       SAFE_FREE(sitename);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       /* only return valid addresses for TCP connections */
+       for (i=0, num_entries = 0; i<count; i++) {
+               if (!is_zero_addr(&ss_list[i].ss) &&
+                               !is_broadcast_addr(&ss_list[i].ss)) {
+                       num_entries++;
+               }
+       }
+       if (num_entries == 0) {
+               SAFE_FREE(ss_list);
+               return NT_STATUS_BAD_NETWORK_NAME;
+       }
+
+       *return_ss_arr = TALLOC_ARRAY(ctx,
+                               struct sockaddr_storage,
+                               num_entries);
+       if (!(*return_ss_arr)) {
+               SAFE_FREE(ss_list);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0, num_entries = 0; i<count; i++) {
+               if (!is_zero_addr(&ss_list[i].ss) &&
+                               !is_broadcast_addr(&ss_list[i].ss)) {
+                       (*return_ss_arr)[num_entries++] = ss_list[i].ss;
+               }
+       }
+
+       status = NT_STATUS_OK;
+       *p_num_entries = num_entries;
+
+       SAFE_FREE(ss_list);
+       return NT_STATUS_OK;
+}
+
 /********************************************************
  Find the IP address of the master browser or DMB for a workgroup.
 *********************************************************/
@@ -1710,20 +1819,25 @@ static NTSTATUS get_dc_list(const char *domain,
                        enum dc_lookup_type lookup_type,
                        bool *ordered)
 {
-       fstring resolve_order;
-       char *saf_servername;
-       pstring pserver;
+       char *resolve_order = NULL;
+       char *saf_servername = NULL;
+       char *pserver = NULL;
        const char *p;
-       char *port_str;
+       char *port_str = NULL;
        int port;
-       fstring name;
+       char *name;
        int num_addresses = 0;
        int  local_count, i, j;
        struct ip_service *return_iplist = NULL;
        struct ip_service *auto_ip_list = NULL;
-       bool done_auto_lookup = False;
+       bool done_auto_lookup = false;
        int auto_count = 0;
        NTSTATUS status;
+       TALLOC_CTX *ctx = talloc_init("get_dc_list");
+
+       if (!ctx) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
        *ordered = False;
 
@@ -1733,23 +1847,31 @@ static NTSTATUS get_dc_list(const char *domain,
           are disabled and ads_only is True, then set the string to
           NULL. */
 
-       fstrcpy(resolve_order, lp_name_resolve_order());
+       resolve_order = talloc_strdup(ctx, lp_name_resolve_order());
+       if (!resolve_order) {
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
+       }
        strlower_m(resolve_order);
        if (lookup_type == DC_ADS_ONLY)  {
                if (strstr( resolve_order, "host")) {
-                       fstrcpy( resolve_order, "ads");
+                       resolve_order = talloc_strdup(ctx, "ads");
 
                        /* DNS SRV lookups used by the ads resolver
                           are already sorted by priority and weight */
                        *ordered = true;
                } else {
-                        fstrcpy(resolve_order, "NULL");
+                        resolve_order = talloc_strdup(ctx, "NULL");
                }
        } else if (lookup_type == DC_KDC_ONLY) {
                /* DNS SRV lookups used by the ads/kdc resolver
                   are already sorted by priority and weight */
                *ordered = true;
-               fstrcpy(resolve_order, "kdc");
+               resolve_order = talloc_strdup(ctx, "kdc");
+       }
+       if (!resolve_order) {
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
        }
 
        /* fetch the server we have affinity for.  Add the
@@ -1758,22 +1880,27 @@ static NTSTATUS get_dc_list(const char *domain,
        saf_servername = saf_fetch( domain);
 
        if (strequal(domain, lp_workgroup()) || strequal(domain, lp_realm())) {
-               pstr_sprintf(pserver, "%s, %s",
+               pserver = talloc_asprintf(NULL, "%s, %s",
                        saf_servername ? saf_servername : "",
                        lp_passwordserver());
        } else {
-               pstr_sprintf(pserver, "%s, *",
+               pserver = talloc_asprintf(NULL, "%s, *",
                        saf_servername ? saf_servername : "");
        }
 
-       SAFE_FREE( saf_servername );
+       SAFE_FREE(saf_servername);
+       if (!pserver) {
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
+       }
 
        /* if we are starting from scratch, just lookup DOMAIN<0x1c> */
 
        if (!*pserver ) {
                DEBUG(10,("get_dc_list: no preferred domain controllers.\n"));
-               return internal_resolve_name(domain, 0x1C, sitename, ip_list,
+               status = internal_resolve_name(domain, 0x1C, sitename, ip_list,
                                             count, resolve_order);
+               goto out;
        }
 
        DEBUG(3,("get_dc_list: preferred server list: \"%s\"\n", pserver ));
@@ -1786,7 +1913,7 @@ static NTSTATUS get_dc_list(const char *domain,
         */
 
        p = pserver;
-       while (next_token(&p,name,LIST_SEP,sizeof(name))) {
+       while (next_token_talloc(ctx, &p, &name, LIST_SEP)) {
                if (strequal(name, "*")) {
                        status = internal_resolve_name(domain, 0x1C, sitename,
                                                       &auto_ip_list,
@@ -1809,18 +1936,19 @@ static NTSTATUS get_dc_list(const char *domain,
        if ((num_addresses == 0)) {
                if (done_auto_lookup) {
                        DEBUG(4,("get_dc_list: no servers found\n"));
-                       SAFE_FREE(auto_ip_list);
-                       return NT_STATUS_NO_LOGON_SERVERS;
+                       status = NT_STATUS_NO_LOGON_SERVERS;
+                       goto out;
                }
-               return internal_resolve_name(domain, 0x1C, sitename, ip_list,
+               status = internal_resolve_name(domain, 0x1C, sitename, ip_list,
                                             count, resolve_order);
+               goto out;
        }
 
        if ((return_iplist = SMB_MALLOC_ARRAY(struct ip_service,
                                        num_addresses)) == NULL) {
                DEBUG(3,("get_dc_list: malloc fail !\n"));
-               SAFE_FREE(auto_ip_list);
-               return NT_STATUS_NO_MEMORY;
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
        }
 
        p = pserver;
@@ -1829,7 +1957,7 @@ static NTSTATUS get_dc_list(const char *domain,
        /* fill in the return list now with real IP's */
 
        while ((local_count<num_addresses) &&
-                       next_token(&p,name,LIST_SEP,sizeof(name))) {
+                       next_token_talloc(ctx, &p, &name, LIST_SEP)) {
                struct sockaddr_storage name_ss;
 
                /* copy any addersses from the auto lookup */
@@ -1896,8 +2024,6 @@ static NTSTATUS get_dc_list(const char *domain,
                }
        }
 
-       SAFE_FREE(auto_ip_list);
-
        /* need to remove duplicates in the list if we have any
           explicit password servers */
 
@@ -1925,7 +2051,13 @@ static NTSTATUS get_dc_list(const char *domain,
        *ip_list = return_iplist;
        *count = local_count;
 
-       return ( *count != 0 ? NT_STATUS_OK : NT_STATUS_NO_LOGON_SERVERS );
+       status = ( *count != 0 ? NT_STATUS_OK : NT_STATUS_NO_LOGON_SERVERS );
+
+  out:
+
+       SAFE_FREE(auto_ip_list);
+       TALLOC_FREE(ctx);
+       return status;
 }
 
 /*********************************************************************