lsa_enum_trust_dom functionality
Rafal Szczesniak
mimir at diament.ists.pwr.wroc.pl
Thu Apr 11 05:17:02 GMT 2002
Here's the patch that adds server side of lsa_enum_trust_dom call to
samba. Memory leak causing segfault to smbd in some cases is already
fixed. Major changes include:
1. tdb_search_keys() is the new utility function searching the keys that
match given pattern. (tdbutil.c and tdbutil.h)
2. tdb_search_list_free() is a clean-up function for results returned by
tdb_search_keys (tdbutil.c and tdbutil.h)
3. secrets_get_trusted_domains() is function that returns given range of
trusted domain entries. The result is required list of trusted domains
(unicode name and sid)
4. stored trusted domain entry (struct trusted_dom_pass) now contains
unicode name together with trust password, last change time and domain
sid.
5. init_r_enum_trust_dom() function is modified (as well as
_lsa_enum_trust_dom() ) to return variable-length response
There's yet one more thing to change, but it's important only when samba
returns large number of entries, so this part of code may be commited now.
cheers,
+------------------------------------------------------------+
|Rafal 'Mimir' Szczesniak <mimir at diament.ists.pwr.wroc.pl> |
|*BSD, GNU/Linux and Samba /
|__________________________________________________________/
-------------- next part --------------
Index: auth/auth_domain.c
===================================================================
RCS file: /cvsroot/samba/source/auth/auth_domain.c,v
retrieving revision 1.33
diff -u -r1.33 auth_domain.c
--- auth/auth_domain.c 27 Mar 2002 00:02:48 -0000 1.33
+++ auth/auth_domain.c 11 Apr 2002 10:30:59 -0000
@@ -527,7 +527,7 @@
}
/*
- * Get the machine account password for the trusted domain
+ * Get the trusted account password for the trusted domain
* No need to become_root() as secrets_init() is done at startup.
*/
Index: include/includes.h
===================================================================
RCS file: /cvsroot/samba/source/include/includes.h,v
retrieving revision 1.261
diff -u -r1.261 includes.h
--- include/includes.h 27 Mar 2002 23:17:50 -0000 1.261
+++ include/includes.h 11 Apr 2002 10:30:59 -0000
@@ -696,6 +696,7 @@
#include "dlinklist.h"
#include "../tdb/tdb.h"
#include "../tdb/spinlock.h"
+#include "../tdb/tdbutil.h"
#include "talloc.h"
#include "ads.h"
#include "interfaces.h"
Index: include/rpc_lsa.h
===================================================================
RCS file: /cvsroot/samba/source/include/rpc_lsa.h,v
retrieving revision 1.39
diff -u -r1.39 rpc_lsa.h
--- include/rpc_lsa.h 30 Jan 2002 06:08:15 -0000 1.39
+++ include/rpc_lsa.h 11 Apr 2002 10:30:59 -0000
@@ -278,8 +278,8 @@
typedef struct lsa_enum_trust_dom_info
{
POLICY_HND pol; /* policy handle */
- uint32 enum_context; /* enumeration context handle */
- uint32 preferred_len; /* preferred maximum length */
+ uint32 enum_context; /* enumeration context handle */
+ uint32 preferred_len; /* preferred maximum length */
} LSA_Q_ENUM_TRUST_DOM;
Index: include/secrets.h
===================================================================
RCS file: /cvsroot/samba/source/include/secrets.h,v
retrieving revision 1.9
diff -u -r1.9 secrets.h
--- include/secrets.h 10 Apr 2002 00:34:59 -0000 1.9
+++ include/secrets.h 11 Apr 2002 10:30:59 -0000
@@ -48,12 +48,27 @@
time_t mod_time;
};
-/* structure for storing trusted domain password */
+/*
+ * storage structure for trusted domain
+ */
struct trusted_dom_pass {
- int pass_len;
- fstring pass;
+ size_t uni_name_len;
+ smb_ucs2_t uni_name[32]; /* unicode domain name */
+ size_t pass_len;
+ fstring pass; /* trust relationship's password */
time_t mod_time;
- DOM_SID domain_sid; /* remote domain's sid */
+ DOM_SID domain_sid; /* remote domain's sid */
};
+
+/*
+ * trusted domain entry/entries returned by secrets_get_trusted_domains
+ * (used in _lsa_enum_trust_dom call)
+ */
+typedef struct trustdom {
+ UNISTR2 name;
+ DOM_SID sid;
+ struct trustdom *next;
+} TRUSTDOM;
+
#endif /* _SECRETS_H */
Index: lib/util_unistr.c
===================================================================
RCS file: /cvsroot/samba/source/lib/util_unistr.c,v
retrieving revision 1.92
diff -u -r1.92 util_unistr.c
--- lib/util_unistr.c 26 Mar 2002 03:15:29 -0000 1.92
+++ lib/util_unistr.c 11 Apr 2002 10:30:59 -0000
@@ -775,3 +775,42 @@
return num_wchars;
}
+
+/**
+ * Samba ucs2 type to UNISTR2 conversion
+ *
+ * @param dst UNISTR2 destination. If equals null, then it's allocated.
+ * @param src smb_ucs2_t source.
+ * @param max_len maximum number of unicode characters to copy. If equals
+ * null, then null-termination of src is taken
+ *
+ * @return copied UNISTR2 destination
+ **/
+UNISTR2* ucs2_to_unistr2(UNISTR2* dst, smb_ucs2_t* src)
+{
+ size_t len;
+
+ if (!src) return NULL;
+ len = strlen_w(src);
+
+ /* allocate UNISTR2 destination if not given */
+ if (!dst) {
+ dst = (UNISTR2*) malloc(sizeof(UNISTR2));
+ if (!dst) return NULL;
+ }
+ if (!dst->buffer) {
+ dst->buffer = (uint16*) malloc(sizeof(uint16) * (len + 1));
+ if (!dst->buffer) return NULL;
+ }
+
+ /* set UNISTR2 parameters */
+ dst->uni_max_len = len + 1;
+ dst->undoc = 0;
+ dst->uni_str_len = len;
+
+ /* copy the actual unicode string */
+ strncpy_w(dst->buffer, src, dst->uni_max_len);
+
+ return dst;
+};
+
Index: passdb/secrets.c
===================================================================
RCS file: /cvsroot/samba/source/passdb/secrets.c,v
retrieving revision 1.32
diff -u -r1.32 secrets.c
--- passdb/secrets.c 10 Mar 2002 01:43:04 -0000 1.32
+++ passdb/secrets.c 11 Apr 2002 10:30:59 -0000
@@ -124,9 +124,13 @@
}
-/************************************************************************
-form a key for fetching the machine trust account password
-************************************************************************/
+/**
+ * Form a key for fetching the machine trust account password
+ *
+ * @param domain domain name
+ *
+ * @return stored password's key
+ **/
char *trust_keystr(char *domain)
{
static fstring keystr;
@@ -141,7 +145,7 @@
/**
* Form a key for fetching a trusted domain password
*
- * @param domain domain name
+ * @param domain trusted domain name
*
* @return stored password's key
**/
@@ -194,21 +198,23 @@
Routine to get account password to trusted domain
************************************************************************/
BOOL secrets_fetch_trusted_domain_password(char *domain, char** pwd,
- DOM_SID *sid, time_t *pass_last_set_time)
+ DOM_SID *sid, time_t *pass_last_set_time)
{
struct trusted_dom_pass *pass;
size_t size;
+ /* fetching trusted domain password structure */
if (!(pass = secrets_fetch(trustdom_keystr(domain), &size))) {
DEBUG(5, ("secrets_fetch failed!\n"));
return False;
}
-
+
if (size != sizeof(*pass)) {
DEBUG(0, ("secrets were of incorrect size!\n"));
return False;
}
-
+
+ /* the trust's password */
if (pwd) {
*pwd = strdup(pass->pass);
if (!*pwd) {
@@ -216,9 +222,12 @@
}
}
+ /* last change time */
if (pass_last_set_time) *pass_last_set_time = pass->mod_time;
+ /* domain sid */
memcpy(&sid, &(pass->domain_sid), sizeof(sid));
+
SAFE_FREE(pass);
return True;
@@ -247,19 +256,30 @@
* @return true if succeeded
**/
-BOOL secrets_store_trusted_domain_password(char* domain, char* pwd,
+BOOL secrets_store_trusted_domain_password(char* domain, uint16* uni_dom_name,
+ size_t uni_name_len, char* pwd,
DOM_SID sid)
{
struct trusted_dom_pass pass;
ZERO_STRUCT(pass);
+ /* unicode domain name and its length */
+ if (!uni_dom_name)
+ return False;
+
+ strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name));
+ pass.uni_name_len = uni_name_len;
+
+ /* last change time */
pass.mod_time = time(NULL);
+ /* password of the trust */
pass.pass_len = strlen(pwd);
fstrcpy(pass.pass, pwd);
+ /* domain sid */
memcpy(&(pass.domain_sid), &sid, sizeof(sid));
-
+
return secrets_store(trustdom_keystr(domain), (void *)&pass, sizeof(pass));
}
@@ -355,5 +375,65 @@
if (*p == ',') *p = '/';
return secrets_store(key, pw, strlen(pw));
+}
+
+
+/**
+ * The caller must take care of doing a proper free of returned list
+ *
+ * @param start_idx starting index, eg. we can start fetching
+ * at third or sixth trusted domain entry
+ * @param num_domains number of domain entries to fetch at one call
+ *
+ * @return list of trusted domains structs (unicode name, sid and password)
+ **/
+
+TRUSTDOM* secrets_get_trusted_domains(TALLOC_CTX* ctx, int start_idx, int num_domains)
+{
+ TDB_LIST_NODE *keys, *k;
+ TRUSTDOM *domains = NULL;
+ char *pattern;
+ int idx = 1;
+ struct trusted_dom_pass *pass;
+
+ /* generate searching pattern */
+ if (!asprintf(&pattern, "%s/*", SECRETS_DOMTRUST_ACCT_PASS))
+ return NULL;
+
+ /* searching for keys in sectrets db -- way to go ... */
+ keys = tdb_search_keys(tdb, pattern);
+
+ /* fetching trusted domains' data and collecting them in a list */
+ k = keys;
+ while (k) {
+ if (idx >= start_idx && idx < start_idx + num_domains) {
+ TRUSTDOM* dom = (TRUSTDOM*) talloc(ctx, sizeof(*domains));
+ dom->next = domains;
+
+ /* important: ensure null-termination of the key string */
+ k->node_key.dptr[k->node_key.dsize] = 0;
+ pass = secrets_fetch(k->node_key.dptr, &k->node_key.dsize);
+
+ /* copy domain sid */
+ memcpy(&dom->sid, (void*)&pass->domain_sid, sizeof(dom->sid));
+
+ /* copy unicode domain name */
+ dom->name.buffer = (smb_ucs2_t*) talloc(ctx, (pass->uni_name_len + 1) * sizeof(uint16));
+ ucs2_to_unistr2(&dom->name, pass->uni_name);
+
+ /* place domain info in the list */
+ domains = dom;
+
+ /* free returned tdb record */
+ SAFE_FREE(pass);
+ };
+
+ k = k->next;
+ }
+
+ /* free the results of searching the keys */
+ tdb_search_list_free(keys);
+
+ return domains;
}
Index: rpc_parse/parse_lsa.c
===================================================================
RCS file: /cvsroot/samba/source/rpc_parse/parse_lsa.c,v
retrieving revision 1.75
diff -u -r1.75 parse_lsa.c
--- rpc_parse/parse_lsa.c 4 Apr 2002 02:39:57 -0000 1.75
+++ rpc_parse/parse_lsa.c 11 Apr 2002 10:31:00 -0000
@@ -523,40 +523,57 @@
Inits an LSA_R_ENUM_TRUST_DOM structure.
********************************************************************/
-void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *r_e, uint32 enum_context,
- char *domain_name, DOM_SID *domain_sid,
- NTSTATUS status)
+void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *r_e, uint32 enum_context,
+ uint32 max_num_domains, TRUSTDOM* td)
{
+ NTSTATUS status;
+ int i = 0;
+
DEBUG(5, ("init_r_enum_trust_dom\n"));
r_e->enum_context = enum_context;
-
- if (NT_STATUS_IS_OK(status)) {
- int len_domain_name = strlen(domain_name) + 1;
+ r_e->num_domains = 0;
+ r_e->ptr_enum_domains = 0;
+ r_e->num_domains2 = 0;
+
+ /*
+ * allocating empty arrays of unicode headers, strings
+ * and sids of enumerated trusted domains
+ */
+ if (!(r_e->hdr_domain_name = (UNIHDR2 *)talloc(ctx,sizeof(UNIHDR2) * max_num_domains)))
+ return;
+
+ if (!(r_e->uni_domain_name = (UNISTR2 *)talloc(ctx,sizeof(UNISTR2) * max_num_domains)))
+ return;
+
+ if (!(r_e->domain_sid = (DOM_SID2 *)talloc(ctx,sizeof(DOM_SID2) * max_num_domains)))
+ return;
+
+ status = NT_STATUS_NO_MORE_ENTRIES;
+
+ while (td) {
+ r_e->num_domains = i + 1;
+ r_e->num_domains2 = i + 1;
+ /* don't know what actually is this for, but pointer is a pointer... :) */
+ r_e->ptr_enum_domains = (uint32) &(r_e->num_domains);
- r_e->num_domains = 1;
- r_e->ptr_enum_domains = 1;
- r_e->num_domains2 = 1;
-
- if (!(r_e->hdr_domain_name = (UNIHDR2 *)talloc(ctx,sizeof(UNIHDR2))))
- return;
+ init_uni_hdr2(&r_e->hdr_domain_name[i], td->name.uni_str_len);
+ init_dom_sid2(&r_e->domain_sid[i], &td->sid);
- if (!(r_e->uni_domain_name = (UNISTR2 *)talloc(ctx,sizeof(UNISTR2))))
- return;
+ /*
+ * important: ensure copy_unistr2 will allocate the buffer
+ * by explicitly setting it to NULL
+ */
+ r_e->uni_domain_name[i].buffer = NULL;
+ copy_unistr2(&r_e->uni_domain_name[i], &td->name);
+
+ i++;
+ td = td->next;
+ status = NT_STATUS_OK;
- if (!(r_e->domain_sid = (DOM_SID2 *)talloc(ctx,sizeof(DOM_SID2))))
- return;
+ };
- init_uni_hdr2(&r_e->hdr_domain_name[0], len_domain_name);
- init_unistr2 (&r_e->uni_domain_name[0], domain_name,
- len_domain_name);
- init_dom_sid2(&r_e->domain_sid[0], domain_sid);
- } else {
- r_e->num_domains = 0;
- r_e->ptr_enum_domains = 0;
- }
-
- r_e->status = status;
+ r_e->status = status;
}
/*******************************************************************
@@ -603,7 +620,7 @@
for (i = 0; i < num_domains; i++) {
if(!smb_io_unistr2 ("", &r_e->uni_domain_name[i],
- r_e->hdr_domain_name[i].buffer,
+ r_e->hdr_domain_name[i].buffer,
ps, depth))
return False;
if(!smb_io_dom_sid2("", &r_e->domain_sid[i], ps,
Index: rpc_server/srv_lsa.c
===================================================================
RCS file: /cvsroot/samba/source/rpc_server/srv_lsa.c,v
retrieving revision 1.78
diff -u -r1.78 srv_lsa.c
--- rpc_server/srv_lsa.c 30 Jan 2002 06:08:33 -0000 1.78
+++ rpc_server/srv_lsa.c 11 Apr 2002 10:31:00 -0000
@@ -105,8 +105,10 @@
if(!lsa_io_q_enum_trust_dom("", &q_u, data, 0))
return False;
+ /* get required trusted domains information */
r_u.status = _lsa_enum_trust_dom(p, &q_u, &r_u);
+ /* prepare the response */
if(!lsa_io_r_enum_trust_dom("", &r_u, rdata, 0))
return False;
Index: rpc_server/srv_lsa_nt.c
===================================================================
RCS file: /cvsroot/samba/source/rpc_server/srv_lsa_nt.c,v
retrieving revision 1.52
diff -u -r1.52 srv_lsa_nt.c
--- rpc_server/srv_lsa_nt.c 9 Apr 2002 04:59:34 -0000 1.52
+++ rpc_server/srv_lsa_nt.c 11 Apr 2002 10:31:00 -0000
@@ -416,14 +416,16 @@
/***************************************************************************
_lsa_enum_trust_dom - this needs fixing to do more than return NULL ! JRA.
+ ufff, done :) mimir
***************************************************************************/
NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_ENUM_TRUST_DOM *r_u)
{
struct lsa_info *info;
- uint32 enum_context = 0;
- char *dom_name = NULL;
- DOM_SID *dom_sid = NULL;
+ uint32 enum_context = q_u->enum_context;
+ /* it's set to 10 as a "our" preferred length */
+ uint32 max_num_domains = q_u->preferred_len < 10 ? q_u->preferred_len : 10;
+ TRUSTDOM *trust_doms;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
@@ -432,9 +434,10 @@
if (!(info->access & POLICY_VIEW_LOCAL_INFORMATION))
return NT_STATUS_ACCESS_DENIED;
- /* set up the LSA QUERY INFO response */
- init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, dom_name, dom_sid,
- dom_name != NULL ? NT_STATUS_OK : NT_STATUS_NO_MORE_ENTRIES);
+ trust_doms = secrets_get_trusted_domains(p->mem_ctx, enum_context, max_num_domains);
+
+ /* set up the lsa_enum_trust_dom response */
+ init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, max_num_domains, trust_doms);
return r_u->status;
}
Index: tdb/tdbutil.c
===================================================================
RCS file: /cvsroot/samba/source/tdb/tdbutil.c,v
retrieving revision 1.38
diff -u -r1.38 tdbutil.c
--- tdb/tdbutil.c 9 Apr 2002 23:03:17 -0000 1.38
+++ tdb/tdbutil.c 11 Apr 2002 10:31:00 -0000
@@ -19,6 +19,7 @@
*/
#include "includes.h"
+#include <fnmatch.h>
/* these are little tdb utility functions that are meant to make
dealing with a tdb database a little less cumbersome in Samba */
@@ -509,3 +510,65 @@
{
return tdb_delete(the_tdb, key);
}
+
+
+
+/**
+ * Search across the whole tdb for keys that match the given pattern
+ * return the result as a list of keys
+ *
+ * @param tdb pointer to opened tdb file context
+ * @param pattern searching pattern used by fnmatch(3) functions
+ *
+ * @return list of keys found by looking up with given pattern
+ **/
+TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern)
+{
+ TDB_DATA key, next;
+ TDB_LIST_NODE *list = NULL;
+
+ for (key = tdb_firstkey(tdb); key.dptr; key = next) {
+ /* duplicate key string to ensure null-termination */
+ char *key_str = (char*) strndup(key.dptr, key.dsize);
+
+ next = tdb_nextkey(tdb, key);
+
+ /* do the pattern checking */
+ if (fnmatch(pattern, key_str, 0) == 0) {
+ TDB_LIST_NODE* rec;
+ rec = (TDB_LIST_NODE*) malloc(sizeof(*rec));
+
+ /* have doubts about this one */
+ rec->next = list;
+ rec->node_key = key;
+ list = rec;
+ } else {
+ free(key.dptr);
+ }
+
+ /* free duplicated key string */
+ free(key_str);
+ }
+
+ return list;
+
+};
+
+
+/**
+ * Free the list returned by tdb_search_keys
+ *
+ * @param node list of results found by tdb_search_keys
+ **/
+void tdb_search_list_free(TDB_LIST_NODE* node)
+{
+ TDB_LIST_NODE *next_node;
+
+ while (node) {
+ next_node = node->next;
+ SAFE_FREE(node);
+ node = next_node;
+ };
+};
+
+
Index: utils/net_rpc.c
===================================================================
RCS file: /cvsroot/samba/source/utils/net_rpc.c,v
retrieving revision 1.14
diff -u -r1.14 net_rpc.c
--- utils/net_rpc.c 5 Apr 2002 01:36:28 -0000 1.14
+++ utils/net_rpc.c 11 Apr 2002 10:31:00 -0000
@@ -1061,10 +1061,8 @@
return -1;
}
- if (cli->nt_pipe_fnum) {
+ if (cli->nt_pipe_fnum)
cli_nt_session_close(cli);
- talloc_destroy(mem_ctx);
- }
/*
@@ -1116,20 +1114,20 @@
if (cli->nt_pipe_fnum)
cli_nt_session_close(cli);
-
- talloc_destroy(mem_ctx);
-
/*
* Store the password in secrets db
*/
- if (!secrets_store_trusted_domain_password(domain_name, opt_password,
+ if (!secrets_store_trusted_domain_password(domain_name, wks_info.uni_lan_grp.buffer,
+ wks_info.uni_lan_grp.uni_str_len, opt_password,
domain_sid)) {
DEBUG(0, ("Storing password for trusted domain failed.\n"));
return -1;
}
+ talloc_destroy(mem_ctx);
+
DEBUG(0, ("Success!\n"));
return 0;
}
diff -Nur samba/source/tdb/tdbutil.h head/source/tdb/tdbutil.h
--- tdb/tdbutil.h Thu Jan 1 01:00:00 1970
+++ tdb/tdbutil.h Wed Apr 10 18:13:25 2002
@@ -0,0 +1,37 @@
+/*
+ Unix SMB/CIFS implementation.
+ tdb utility functions
+ Copyright (C) Andrew Tridgell 1999
+
+ 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 __TDBUTIL_H__
+#define __TDBUTIL_H__
+
+
+/* single node of a list returned by tdb_search_keys */
+typedef struct keys_node
+{
+ struct keys_node *next;
+ TDB_DATA node_key;
+} TDB_LIST_NODE;
+
+
+TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT*, const char*);
+void tdb_search_list_free(TDB_LIST_NODE*);
+
+
+#endif /* __TDBUTIL_H__ */
More information about the samba-technical
mailing list