summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/lib/samba3/config.mk5
-rw-r--r--source4/lib/samba3/group.c2
-rw-r--r--source4/lib/samba3/idmap.c2
-rw-r--r--source4/lib/samba3/policy.c4
-rw-r--r--source4/lib/samba3/policy.h37
-rw-r--r--source4/lib/samba3/samba3.h (renamed from source4/lib/samba3/sam.h)49
-rw-r--r--source4/lib/samba3/samba3dump.c3
-rw-r--r--source4/lib/samba3/secrets.c160
-rw-r--r--source4/lib/samba3/tdbsam.c2
-rw-r--r--source4/lib/samba3/winsdb.c179
10 files changed, 339 insertions, 104 deletions
diff --git a/source4/lib/samba3/config.mk b/source4/lib/samba3/config.mk
index ba6c1a8dbc..15802d3b8e 100644
--- a/source4/lib/samba3/config.mk
+++ b/source4/lib/samba3/config.mk
@@ -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
################################################
diff --git a/source4/lib/samba3/group.c b/source4/lib/samba3/group.c
index b8cc0d6819..d7097f596a 100644
--- a/source4/lib/samba3/group.c
+++ b/source4/lib/samba3/group.c
@@ -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"
diff --git a/source4/lib/samba3/idmap.c b/source4/lib/samba3/idmap.c
index c541c5bc92..64d6387ed4 100644
--- a/source4/lib/samba3/idmap.c
+++ b/source4/lib/samba3/idmap.c
@@ -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 */
diff --git a/source4/lib/samba3/policy.c b/source4/lib/samba3/policy.c
index 796e6eefac..bfb3ac373e 100644
--- a/source4/lib/samba3/policy.c
+++ b/source4/lib/samba3/policy.c
@@ -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/source4/lib/samba3/policy.h b/source4/lib/samba3/policy.h
deleted file mode 100644
index b41f38a394..0000000000
--- a/source4/lib/samba3/policy.h
+++ /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 */
diff --git a/source4/lib/samba3/sam.h b/source4/lib/samba3/samba3.h
index bc13b28e2a..d3e03cf923 100644
--- a/source4/lib/samba3/sam.h
+++ b/source4/lib/samba3/samba3.h
@@ -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_H
+#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 */
diff --git a/source4/lib/samba3/samba3dump.c b/source4/lib/samba3/samba3dump.c
index 72052092ff..6bcfce96fa 100644
--- a/source4/lib/samba3/samba3dump.c
+++ b/source4/lib/samba3/samba3dump.c
@@ -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";
diff --git a/source4/lib/samba3/secrets.c b/source4/lib/samba3/secrets.c
index ccd53c0398..ab19f166ee 100644
--- a/source4/lib/samba3/secrets.c
+++ b/source4/lib/samba3/secrets.c
@@ -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("");
}
}
+
+
diff --git a/source4/lib/samba3/tdbsam.c b/source4/lib/samba3/tdbsam.c
index a16c07d2d1..aba01d0db6 100644
--- a/source4/lib/samba3/tdbsam.c
+++ b/source4/lib/samba3/tdbsam.c
@@ -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/source4/lib/samba3/winsdb.c b/source4/lib/samba3/winsdb.c
new file mode 100644
index 0000000000..7c3253e101
--- /dev/null
+++ b/source4/lib/samba3/winsdb.c
@@ -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;
+}