r9555: More updates. Everything except for secrets.c compiles now..
authorJelmer Vernooij <jelmer@samba.org>
Wed, 24 Aug 2005 00:58:52 +0000 (00:58 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:34:28 +0000 (13:34 -0500)
source/lib/samba3/config.mk
source/lib/samba3/group.c
source/lib/samba3/idmap.c
source/lib/samba3/policy.c
source/lib/samba3/policy.h [deleted file]
source/lib/samba3/samba3.h [moved from source/lib/samba3/sam.h with 70% similarity]
source/lib/samba3/samba3dump.c
source/lib/samba3/secrets.c
source/lib/samba3/tdbsam.c
source/lib/samba3/winsdb.c [new file with mode: 0644]

index ba6c1a8dbc2df622bd8f700d84173ee2e724e28a..15802d3b8ed2719e507ac8a3bf457803be405cba 100644 (file)
@@ -4,7 +4,10 @@
 INIT_OBJ_FILES = \
                lib/samba3/smbpasswd.o \
                lib/samba3/tdbsam.o \
-               lib/samba3/policy.o
+               lib/samba3/policy.o \
+               lib/samba3/idmap.o \
+               lib/samba3/winsdb.o
+#              lib/samba3/secrets.o
 # End SUBSYSTEM LIBSAMBA3
 ################################################
 
index b8cc0d6819a88d1053c6b849f454a9eeee70345e..d7097f596a499d516fa2ce46c10d89fe38f207c3 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "includes.h"
 #include "system/iconv.h"
-#include "lib/samba3/sam.h"
+#include "lib/samba3/samba3.h"
 #include "lib/tdb/include/tdbutil.h"
 #include "system/filesys.h"
 
index c541c5bc92fe664727f791afd8dd689f86767e40..64d6387ed45095346fde9c080888134689ce0780 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "includes.h"
 #include "lib/tdb/include/tdbutil.h"
-#include "lib/samba3/sam.h"
+#include "lib/samba3/samba3.h"
 #include "system/filesys.h"
 
 /* High water mark keys */
index 796e6eefac54c1e33928333bd12ed122c790e222..bfb3ac373eb56958e0316717369851f9337c90e4 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "includes.h"
 #include "lib/tdb/include/tdbutil.h"
-#include "lib/samba3/policy.h"
+#include "lib/samba3/samba3.h"
 #include "system/filesys.h"
 
 #define DATABASE_VERSION 2
@@ -65,3 +65,5 @@ struct samba3_policy *samba3_read_account_policy(TALLOC_CTX *ctx, const char *fn
        return ret;
 }
 
+
+/* FIXME: Read privileges as well */
diff --git a/source/lib/samba3/policy.h b/source/lib/samba3/policy.h
deleted file mode 100644 (file)
index b41f38a..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 
-   Unix SMB/CIFS implementation.
-   Copyright (C) Jelmer Vernooij                       2005.
-   
-   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
-   (at your option) any later version.
-   
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   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.
-*/
-
-#ifndef _SAMBA3_POLICY_H /* _SAMBA3_POLICY_H */
-#define _SAMBA3_POLICY_H 
-
-struct samba3_policy
-{
-       uint32_t min_password_length;
-       uint32_t password_history;
-       uint32_t user_must_logon_to_change_password;
-       uint32_t maximum_password_age;
-       uint32_t minimum_password_age;
-       uint32_t lockout_duration;
-       uint32_t reset_count_minutes;
-       uint32_t bad_lockout_minutes;
-       uint32_t disconnect_time;
-       uint32_t refuse_machine_password_change;
-};
-
-#endif /* _SAMBA3_POLICY_H */
similarity index 70%
rename from source/lib/samba3/sam.h
rename to source/lib/samba3/samba3.h
index bc13b28e2a8729a4934ef3d8dc0d759b7df66be5..d3e03cf923d1c850e73fac8a6cb966c934b82823 100644 (file)
@@ -1,6 +1,6 @@
 /* 
    Unix SMB/CIFS implementation.
-   Registry interface
+   Samba3 interfaces
    Copyright (C) Jelmer Vernooij                       2005.
    
    This program is free software; you can redistribute it and/or modify
@@ -18,8 +18,8 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#ifndef _SAMBA3_SAM_H /* _SAMBA3_SAM_H */
-#define _SAMBA3_SAM_
+#ifndef _SAMBA3_H /* _SAMBA3_H */
+#define _SAMBA3_H 
 
 #include "librpc/gen_ndr/security.h"
 
@@ -75,4 +75,45 @@ struct samba3_groupmapping {
        const char *comment;
 };
 
-#endif /* _SAMBA3_SAM_H */
+struct samba3_idmap_mapping
+{
+       enum { IDMAP_GROUP, IDMAP_USER } type;
+       uint32_t unix_id;
+       struct dom_sid *sid;
+};
+
+struct samba3_idmap 
+{
+       /* High water marks */
+       uint32_t user_hwm;
+       uint32_t group_hwm;
+
+       uint32_t mapping_count;
+       struct samba3_idmap_mapping *mappings;
+};
+
+struct samba3_winsdb_entry 
+{
+       char *name;
+       int nb_flags;
+       int type;
+       time_t ttl;
+       uint32_t ip_count;
+       struct ipv4_addr *ips;
+};
+
+struct samba3_policy
+{
+       uint32_t min_password_length;
+       uint32_t password_history;
+       uint32_t user_must_logon_to_change_password;
+       uint32_t maximum_password_age;
+       uint32_t minimum_password_age;
+       uint32_t lockout_duration;
+       uint32_t reset_count_minutes;
+       uint32_t bad_lockout_minutes;
+       uint32_t disconnect_time;
+       uint32_t refuse_machine_password_change;
+};
+
+#endif /* _SAMBA3_H */
index 72052092ffc987c4ee27fdcd4bc7b8bef1d33ff0..6bcfce96fadc676429648a806abb453d91f25cd2 100644 (file)
@@ -20,8 +20,7 @@
 */
 
 #include "includes.h"
-#include "lib/samba3/policy.h"
-#include "lib/samba3/sam.h"
+#include "lib/samba3/samba3.h"
 #include "lib/cmdline/popt_common.h"
 
 static const char *libdir = "/var/lib/samba";
index ccd53c03986066e2ae7c14a06d1c16707e237725..ab19f166eefd3d542d202fb79297cb543e73fe62 100644 (file)
@@ -42,6 +42,7 @@
 #include "tdb.h"
 #include "system/filesys.h"
 #include "librpc/gen_ndr/ndr_security.h"
+#include "lib/tdb/include/tdbutil.h"
 
 /* structure for storing machine account password
    (ie. when samba server is member of a domain */
@@ -57,6 +58,78 @@ struct afs_key {
        char key[8];
 };
 
+/*
+ * storage structure for trusted domain
+ */
+typedef struct trusted_dom_pass {
+       size_t uni_name_len;
+       const char *uni_name[32]; /* unicode domain name */
+       size_t pass_len;
+       const char *pass;               /* trust relationship's password */
+       time_t mod_time;
+       struct dom_sid domain_sid;      /* remote domain's sid */
+} TRUSTED_DOM_PASS;
+
+/**
+ * Unpack SID into a pointer
+ *
+ * @param pack_buf pointer to buffer with packed representation
+ * @param bufsize size of the buffer
+ * @param sid pointer to sid structure to be filled with unpacked data
+ *
+ * @return size of structure unpacked from buffer
+ **/
+static size_t tdb_sid_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, struct dom_sid* sid)
+{
+       int idx, len = 0;
+       
+       if (!sid || !pack_buf) return -1;
+
+       len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "bb",
+                         &sid->sid_rev_num, &sid->num_auths);
+                         
+       for (idx = 0; idx < 6; idx++) {
+               len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]);
+       }
+       
+       for (idx = 0; idx < 15; idx++) {
+               len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]);
+       }
+       
+       return len;
+}
+
+/**
+ * Unpack TRUSTED_DOM_PASS passed by pointer
+ *
+ * @param pack_buf pointer to buffer with packed representation
+ * @param bufsize size of the buffer
+ * @param pass pointer to trusted domain password to be filled with unpacked data
+ *
+ * @return size of structure unpacked from buffer
+ **/
+static size_t tdb_trusted_dom_pass_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass)
+{
+       int idx, len = 0;
+       
+       if (!pack_buf || !pass) return -1;
+
+       /* unpack unicode domain name and plaintext password */
+       len += tdb_unpack(tdb, pack_buf, bufsize - len, "d", &pass->uni_name_len);
+       
+       for (idx = 0; idx < 32; idx++)
+               len +=  tdb_unpack(tdb, pack_buf + len, bufsize - len, "w", &pass->uni_name[idx]);
+
+       len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "dPd", &pass->pass_len, &pass->pass,
+                         &pass->mod_time);
+       
+       /* unpack domain sid */
+       len += tdb_sid_unpack(tdb, pack_buf + len, bufsize - len, &pass->domain_sid);
+       
+       return len;     
+}
+
+
 static TDB_CONTEXT *secrets_open(const char *fname)
 {
        TDB_CONTEXT *tdb = tdb_open(fname, 0, TDB_DEFAULT, O_RDONLY, 0600);
@@ -69,31 +142,18 @@ static TDB_CONTEXT *secrets_open(const char *fname)
        return tdb;
 }
 
-/* read a entry from the secrets database - the caller must free the result
-   if size is non-null then the size of the entry is put in there
- */
-static void *secrets_fetch(TDB_CONTEXT *tdb, const char *key, size_t *size)
-{
-       TDB_DATA kbuf, dbuf;
-       
-       kbuf.dptr = strdup(key);
-       kbuf.dsize = strlen(key);
-       dbuf = tdb_fetch(tdb, kbuf);
-       if (size)
-               *size = dbuf.dsize;
-       free(kbuf.dptr);
-       return dbuf.dptr;
-}
-
 static BOOL secrets_fetch_domain_sid(TDB_CONTEXT *tdb, const char *domain, struct dom_sid *sid)
 {
        struct dom_sid *dyn_sid;
+       TDB_DATA val;
        char *key;
        size_t size;
 
        asprintf(&key, "%s/%s", SECRETS_DOMAIN_SID, domain);
        strupper_m(key);
-       dyn_sid = (struct dom_sid *)secrets_fetch(tdb, key, &size);
+       
+       val = tdb_fetch_bystring(tdb, key);
+       /* FIXME: Convert val to dyn_sid */
        SAFE_FREE(key);
 
        if (dyn_sid == NULL)
@@ -114,17 +174,20 @@ static BOOL secrets_fetch_domain_guid(TDB_CONTEXT *tdb, const char *domain, stru
 {
        struct GUID *dyn_guid;
        char *key;
+       TDB_DATA val;
        size_t size;
 
        asprintf(&key, "%s/%s", SECRETS_DOMAIN_GUID, domain);
        strupper_m(key);
-       dyn_guid = (struct GUID *)secrets_fetch(tdb, key, &size);
+       val = tdb_fetch_bystring(tdb, key);
+
+       dyn_guid = (struct GUID *)val.dptr;
 
        if (!dyn_guid) {
                return False;
        }
 
-       if (size != sizeof(struct GUID))
+       if (val.dsize != sizeof(struct GUID))
        { 
                DEBUG(1,("GUID size %d is wrong!\n", (int)size));
                SAFE_FREE(dyn_guid);
@@ -183,7 +246,7 @@ static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb,
 {
        struct machine_acct_pass *pass;
        char *plaintext;
-       size_t size;
+       TDB_DATA val;
 
        plaintext = secrets_fetch_machine_password(tdb, domain, pass_last_set_time, 
                                                   channel);
@@ -193,23 +256,22 @@ static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb,
                SAFE_FREE(plaintext);
                return True;
        }
-
-       if (!(pass = secrets_fetch(tdb, trust_keystr(domain), &size))) {
-               DEBUG(5, ("secrets_fetch failed!\n"));
+       
+       val = tdb_fetch_bystring(tdb, trust_keystr(domain));
+       if (!val.dptr) {
+               DEBUG(5, ("tdb_fetch_bystring failed!\n"));
                return False;
        }
        
-       if (size != sizeof(*pass)) {
+       if (val.dsize != sizeof(*pass)) {
                DEBUG(0, ("secrets were of incorrect size!\n"));
                return False;
        }
 
+       pass = (struct machine_acct_pass *)val.dptr;
+
        if (pass_last_set_time) *pass_last_set_time = pass->mod_time;
        memcpy(ret_pwd, pass->hash, 16);
-       SAFE_FREE(pass);
-
-       if (channel) 
-               *channel = get_default_sec_channel();
 
        return True;
 }
@@ -221,25 +283,24 @@ static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb,
 static BOOL secrets_fetch_trusted_domain_password(TDB_CONTEXT *tdb, const char *domain, char** pwd, struct dom_sid **sid, time_t *pass_last_set_time)
 {
        struct trusted_dom_pass pass;
-       size_t size;
        
        /* unpacking structures */
-       char* pass_buf;
        int pass_len = 0;
+       TDB_DATA val;
 
        ZERO_STRUCT(pass);
 
        /* fetching trusted domain password structure */
-       if (!(pass_buf = secrets_fetch(tdb, trustdom_keystr(domain), &size))) {
+       val = tdb_fetch_bystring(tdb, trustdom_keystr(domain));
+       if (!val.dptr) {
                DEBUG(5, ("secrets_fetch failed!\n"));
                return False;
        }
 
        /* unpack trusted domain password */
-       pass_len = tdb_trusted_dom_pass_unpack(pass_buf, size, &pass);
-       SAFE_FREE(pass_buf);
+       pass_len = tdb_trusted_dom_pass_unpack(val.dptr, val.dsize, &pass);
 
-       if (pass_len != size) {
+       if (pass_len != val.dsize) {
                DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n"));
                return False;
        }
@@ -272,38 +333,23 @@ static char *secrets_fetch_machine_password(TDB_CONTEXT *tdb, const char *domain
 {
        char *key = NULL;
        char *ret;
+       TDB_DATA val;
        asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain);
        strupper_m(key);
-       ret = (char *)secrets_fetch(tdb, key, NULL);
+       val = tdb_fetch_bystring(tdb, key);
        SAFE_FREE(key);
        
        if (pass_last_set_time) {
-               size_t size;
-               uint32_t *last_set_time;
                asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain);
                strupper_m(key);
-               last_set_time = secrets_fetch(tdb, key, &size);
-               if (last_set_time) {
-                       *pass_last_set_time = IVAL(last_set_time,0);
-                       SAFE_FREE(last_set_time);
-               } else {
-                       *pass_last_set_time = 0;
-               }
+               tdb_fetch_uint32(tdb, key, (uint32_t *)pass_last_set_time);
                SAFE_FREE(key);
        }
        
        if (channel) {
-               size_t size;
-               uint32_t *channel_type;
                asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain);
                strupper_m(key);
-               channel_type = secrets_fetch(tdb, key, &size);
-               if (channel_type) {
-                       *channel = IVAL(channel_type,0);
-                       SAFE_FREE(channel_type);
-               } else {
-                       *channel = get_default_sec_channel();
-               }
+               tdb_fetch_uint32(tdb, key, channel);
                SAFE_FREE(key);
        }
        
@@ -317,12 +363,14 @@ static BOOL fetch_ldap_pw(TDB_CONTEXT *tdb, const char *dn, char** pw)
 {
        char *key = NULL;
        size_t size;
+       TDB_DATA val;
        
        if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
                DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
        }
        
-       *pw=secrets_fetch(tdb, key, &size);
+       val = tdb_fetch_bystring(tdb, key);
+       *pw = val.dptr;
        SAFE_FREE(key);
 
        if (!size) {
@@ -363,8 +411,6 @@ static NTSTATUS secrets_get_trusted_domains(TDB_CONTEXT *tdb, TALLOC_CTX* ctx, i
        struct trusted_dom_pass *pass = talloc(ctx, struct trusted_dom_pass);
        NTSTATUS status;
 
-       if (!secrets_init()) return NT_STATUS_ACCESS_DENIED;
-       
        if (!pass) {
                DEBUG(0, ("talloc_zero failed!\n"));
                return NT_STATUS_NO_MEMORY;
@@ -540,3 +586,5 @@ static void secrets_fetch_ipc_userpass(TDB_CONTEXT *tdb, char **username, char *
                *password = smb_xstrdup("");
        }
 }
+
+
index a16c07d2d10f4177371e2ebebb0e4c57e4141971..aba01d0db60cc8435b16db27b9d6266dd89d6823 100644 (file)
@@ -28,7 +28,7 @@
 #include "system/iconv.h"
 #include "system/filesys.h"
 #include "lib/tdb/include/tdbutil.h"
-#include "lib/samba3/sam.h"
+#include "lib/samba3/samba3.h"
 
 #define TDB_FORMAT_STRING_V0       "ddddddBBBBBBBBBBBBddBBwdwdBwwd"
 #define TDB_FORMAT_STRING_V1       "dddddddBBBBBBBBBBBBddBBwdwdBwwd"
diff --git a/source/lib/samba3/winsdb.c b/source/lib/samba3/winsdb.c
new file mode 100644 (file)
index 0000000..7c3253e
--- /dev/null
@@ -0,0 +1,179 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Wins Database
+
+   Copyright (C) Jeremy Allison 1994-2003
+   Copyright (C) Jelmer Vernooij 2005
+
+   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
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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.
+   
+*/
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "pstring.h"
+#include "lib/samba3/samba3.h"
+
+#define WINS_VERSION 1
+
+NTSTATUS samba3_read_winsdb( const char *fn, TALLOC_CTX *ctx, struct samba3_winsdb_entry **entries, uint32_t *count )
+{
+       XFILE *fp;
+       char *line;
+
+       if((fp = x_fopen(fn,O_RDONLY,0)) == NULL) {
+               DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
+                       fn, strerror(errno) ));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       *count = 0;
+       *entries = NULL;
+
+       while (!x_feof(fp)) {
+               struct samba3_winsdb_entry entry;
+               pstring name_str, ip_str, ttl_str, nb_flags_str;
+               const char *ptr;
+               char *p;
+               BOOL got_token;
+               BOOL was_ip;
+               int i;
+               unsigned int hash;
+               int version;
+
+               /* Read a line from the wins.dat file. Strips whitespace
+                       from the beginning and end of the line.  */
+               line = fgets_slash(NULL,-1,fp);
+               if (!line) 
+                       return NT_STATUS_UNSUCCESSFUL;
+      
+               if (*line == '#') {
+                       SAFE_FREE(line);
+                       continue;
+               }
+
+               if (strncmp(line,"VERSION ", 8) == 0) {
+                       if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
+                                               version != WINS_VERSION) {
+                               DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
+                               SAFE_FREE(line);
+                               x_fclose(fp);
+                               return NT_STATUS_UNSUCCESSFUL;
+                       }
+                       SAFE_FREE(line);
+
+                       continue;
+               }
+
+               ptr = line;
+
+               /* 
+                * Now we handle multiple IP addresses per name we need
+                * to iterate over the line twice. The first time to
+                * determine how many IP addresses there are, the second
+                * time to actually parse them into the ip_list array.
+                */
+
+               if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) {
+                       DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
+                       SAFE_FREE(line);
+                       continue;
+               }
+
+               if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) {
+                       DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
+                       SAFE_FREE(line);
+                       continue;
+               }
+
+               /*
+                * Determine the number of IP addresses per line.
+                */
+               entry.ip_count = 0;
+               do {
+                       got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
+                       was_ip = False;
+
+                       if(got_token && strchr(ip_str, '.')) {
+                               entry.ip_count++;
+                               was_ip = True;
+                       }
+               } while( got_token && was_ip);
+
+               if(entry.ip_count == 0) {
+                       DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
+                       SAFE_FREE(line);
+                       continue;
+               }
+
+               if(!got_token) {
+                       DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
+                       SAFE_FREE(line);
+                       continue;
+               }
+
+               /* Allocate the space for the ip_list. */
+               if((entry.ips = talloc_array ( ctx, struct ipv4_addr, entry.ip_count)) == NULL) {
+                       DEBUG(0,("initialise_wins: Malloc fail !\n"));
+                       SAFE_FREE(line);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               /* Reset and re-parse the line. */
+               ptr = line;
+               next_token(&ptr,name_str,NULL,sizeof(name_str)); 
+               next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
+               for(i = 0; i < entry.ip_count; i++) {
+                       next_token(&ptr, ip_str, NULL, sizeof(ip_str));
+                       entry.ips[i] = interpret_addr2(ip_str);
+               }
+               next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
+
+               /* 
+                * Deal with SELF or REGISTER name encoding. Default is REGISTER
+                * for compatibility with old nmbds.
+                */
+
+               if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
+                       DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
+                       talloc_free(entry.ips);
+                       SAFE_FREE(line);
+                       continue;
+               }
+      
+               if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
+                       nb_flags_str[strlen(nb_flags_str)-1] = '\0';
+      
+               /* Netbios name. # divides the name from the type (hex): netbios#xx */
+               entry.name = talloc_strdup(ctx, name_str);
+      
+               if((p = strchr(entry.name,'#')) != NULL) {
+                       *p = 0;
+                       sscanf(p+1,"%x",&entry.type);
+               }
+      
+               /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
+               sscanf(nb_flags_str,"%x",&entry.nb_flags);
+               entry.ttl = atol(ttl_str);
+
+               *entries = talloc_realloc(ctx, *entries, struct samba3_winsdb_entry, (*count)+1);
+               *entries[*count] = entry;
+
+               (*count)++;
+       } 
+    
+       x_fclose(fp);
+       return NT_STATUS_OK;
+}