[SCM] Samba Shared Repository - branch v3-5-test updated

Volker Lendecke vlendec at samba.org
Sun Dec 6 05:08:29 MST 2009


The branch, v3-5-test has been updated
       via  d8a40f1... s3: Fix a const discard warning
       via  0249e47... s3: talloc_array_length deals file with a NULL argument
       via  3c5e571... s3: Small simplification: qsort deals fine with just one entry
       via  4b3ad25... s3: Simplify usr_info_cmp by calling timeval_compare()
       via  d8c5222... s3: Add rpcclient wkssvc_enumerateusers
       via  381cf92... s3: Complete support for NetWkstaGetInfo/NetWkstaEnumUsers
       via  34fc32b... s3: First cut at _wkssvc_NetWkstaEnumUsers
       via  7ead9dd... s3: Support NetWkstaGetInfo 101 and 102
      from  ef33b60... packaging(RHEL-CTDB): package dbwrap_tool and dbwrap_torture in the common pkg

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-5-test


- Log -----------------------------------------------------------------
commit d8a40f1227132d49051ddbc2bb9727ee3956d86c
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Dec 6 12:50:51 2009 +0100

    s3: Fix a const discard warning

commit 0249e477edee01ba4185db8ffada537e8bae8e79
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Dec 6 12:50:25 2009 +0100

    s3: talloc_array_length deals file with a NULL argument

commit 3c5e571a2f1b6d32b735e26949b9739fc960c22b
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Dec 6 12:49:46 2009 +0100

    s3: Small simplification: qsort deals fine with just one entry

commit 4b3ad2547c452dd9493fe63e056346a5f7561a37
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Dec 6 12:49:09 2009 +0100

    s3: Simplify usr_info_cmp by calling timeval_compare()

commit d8c52227224771cbe55a469eec7530f91dc18e26
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Dec 6 12:40:44 2009 +0100

    s3: Add rpcclient wkssvc_enumerateusers

commit 381cf92adb3710d350e39f4a5cd72265a67e3b0a
Author: Ian Puleston <ipuleston at sonicwall.com>
Date:   Mon Nov 23 00:00:00 2009 +0100

    s3: Complete support for NetWkstaGetInfo/NetWkstaEnumUsers

commit 34fc32b9a71334217e4661525ed466d5d57642d2
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Aug 3 17:27:11 2009 +0200

    s3: First cut at _wkssvc_NetWkstaEnumUsers
    
    This needs access checks!

commit 7ead9dd7e8eece7b09d33fdc2ed0f83da0b41e7d
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Aug 3 16:52:01 2009 +0200

    s3: Support NetWkstaGetInfo 101 and 102

-----------------------------------------------------------------------

Summary of changes:
 source3/configure.in               |    2 +-
 source3/rpc_server/srv_wkssvc_nt.c |  536 ++++++++++++++++++++++++++++++++++--
 source3/rpcclient/cmd_wkssvc.c     |   51 ++++
 3 files changed, 570 insertions(+), 19 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/configure.in b/source3/configure.in
index 16eb5d1..adb0339 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -2212,7 +2212,7 @@ dnl  We need to check for many of them
 dnl  But we don't need to do each and every one, because our code uses
 dnl  mostly just the utmp (not utmpx) fields.
 
-AC_CHECK_FUNCS(pututline pututxline updwtmp updwtmpx getutmpx)
+AC_CHECK_FUNCS(pututline pututxline updwtmp updwtmpx getutmpx getutxent)
 
 AC_CACHE_CHECK([for ut_name in utmp],samba_cv_HAVE_UT_UT_NAME,[
 AC_TRY_COMPILE([#include <sys/types.h>
diff --git a/source3/rpc_server/srv_wkssvc_nt.c b/source3/rpc_server/srv_wkssvc_nt.c
index 1831b79..d7f3f82 100644
--- a/source3/rpc_server/srv_wkssvc_nt.c
+++ b/source3/rpc_server/srv_wkssvc_nt.c
@@ -30,12 +30,235 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
+struct dom_usr {
+	char *name;
+	char *domain;
+	time_t login_time;
+};
+
+#ifdef HAVE_GETUTXENT
+
+#include <utmpx.h>
+
+struct usrinfo {
+	char *name;
+	struct timeval login_time;
+};
+
+static int usr_info_cmp(const void *p1, const void *p2)
+{
+	const struct usrinfo *usr1 = (const struct usrinfo *)p1;
+	const struct usrinfo *usr2 = (const struct usrinfo *)p2;
+
+	/* Called from qsort to compare two users in a usrinfo_t array for
+	 * sorting by login time. Return >0 if usr1 login time was later than
+	 * usr2 login time, <0 if it was earlier */
+	return timeval_compare(&usr1->login_time, &usr2->login_time);
+}
+
+/*******************************************************************
+ Get a list of the names of all users logged into this machine
+ ********************************************************************/
+
+static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
+{
+	char **users;
+	int i, num_users = 0;
+	struct usrinfo *usr_infos = NULL;
+	struct utmpx *u;
+
+	while ((u = getutxent()) != NULL) {
+		struct usrinfo *tmp;
+		if (u->ut_type != USER_PROCESS) {
+			continue;
+		}
+		for (i = 0; i < num_users; i++) {
+			/* getutxent can return multiple user entries for the
+			 * same user, so ignore any dups */
+			if (strcmp(u->ut_user, usr_infos[i].name) == 0) {
+				break;
+			}
+		}
+		if (i < num_users) {
+			continue;
+		}
+
+		tmp = talloc_realloc(mem_ctx, usr_infos, struct usrinfo,
+				     num_users+1);
+		if (tmp == NULL) {
+			TALLOC_FREE(tmp);
+			endutxent();
+			return NULL;
+		}
+		usr_infos = tmp;
+		usr_infos[num_users].name = talloc_strdup(usr_infos,
+							  u->ut_user);
+		if (usr_infos[num_users].name == NULL) {
+			TALLOC_FREE(usr_infos);
+			endutxent();
+			return NULL;
+		}
+		usr_infos[num_users].login_time.tv_sec = u->ut_tv.tv_sec;
+		usr_infos[num_users].login_time.tv_usec = u->ut_tv.tv_usec;
+		num_users += 1;
+	}
+
+	/* Sort the user list by time, oldest first */
+	qsort(usr_infos, num_users, sizeof(struct usrinfo), usr_info_cmp);
+
+	users = (char**)talloc_array(mem_ctx, char*, num_users);
+	if (users) {
+		for (i = 0; i < num_users; i++) {
+			users[i] = talloc_move(users, &usr_infos[i].name);
+		}
+	}
+	TALLOC_FREE(usr_infos);
+	endutxent();
+	errno = 0;
+	return users;
+}
+
+#else
+
+static char **get_logged_on_userlist(TALLOC_CTX *mem_ctx)
+{
+	return NULL;
+}
+
+#endif
+
+static int dom_user_cmp(const void *p1, const void *p2)
+{
+	/* Called from qsort to compare two domain users in a dom_usr_t array
+	 * for sorting by login time. Return >0 if usr1 login time was later
+	 * than usr2 login time, <0 if it was earlier */
+	const struct dom_usr *usr1 = (const struct dom_usr *)p1;
+	const struct dom_usr *usr2 = (const struct dom_usr *)p2;
+
+	return (usr1->login_time - usr2->login_time);
+}
+
+/*******************************************************************
+ Get a list of the names of all users of this machine who are
+ logged into the domain.
+
+ This should return a list of the users on this machine who are
+ logged into the domain (i.e. have been authenticated by the domain's
+ password server) but that doesn't fit well with the normal Samba
+ scenario where accesses out to the domain are made through smbclient
+ with each such session individually authenticated. So about the best
+ we can do currently is to list sessions of local users connected to
+ this server, which means that to get themself included in the list a
+ local user must create a session to the local samba server by running:
+     smbclient \\\\localhost\\share
+
+ FIXME: find a better way to get local users logged into the domain
+ in this list.
+ ********************************************************************/
+
+static struct dom_usr *get_domain_userlist(TALLOC_CTX *mem_ctx)
+{
+	struct sessionid *session_list = NULL;
+	char *machine_name, *p, *nm;
+	const char *sep;
+	struct dom_usr *users, *tmp;
+	int i, num_users, num_sessions;
+
+	sep = lp_winbind_separator();
+	if (!sep) {
+		sep = "\\";
+	}
+
+	num_sessions = list_sessions(mem_ctx, &session_list);
+	if (num_sessions == 0) {
+		errno = 0;
+		return NULL;
+	}
+
+	users = talloc_array(mem_ctx, struct dom_usr, num_sessions);
+	if (users == NULL) {
+		TALLOC_FREE(session_list);
+		return NULL;
+	}
+
+	for (i=num_users=0; i<num_sessions; i++) {
+		if (!session_list[i].username
+		    || !session_list[i].remote_machine) {
+			continue;
+		}
+		p = strpbrk(session_list[i].remote_machine, "./");
+		if (p) {
+			*p = '\0';
+		}
+		machine_name = talloc_asprintf_strupper_m(
+			users, "%s", session_list[i].remote_machine);
+		if (machine_name == NULL) {
+			DEBUG(10, ("talloc_asprintf failed\n"));
+			continue;
+		}
+		if (strcmp(machine_name, global_myname()) == 0) {
+			p = session_list[i].username;
+			nm = strstr(p, sep);
+			if (nm) {
+				/*
+				 * "domain+name" format so split domain and
+				 * name components
+				 */
+				*nm = '\0';
+				nm += strlen(sep);
+				users[num_users].domain =
+					talloc_asprintf_strupper_m(users,
+								   "%s", p);
+				users[num_users].name = talloc_strdup(users,
+								      nm);
+			} else {
+				/*
+				 * Simple user name so get domain from smb.conf
+				 */
+				users[num_users].domain =
+					talloc_strdup(users, lp_workgroup());
+				users[num_users].name = talloc_strdup(users,
+								      p);
+			}
+			users[num_users].login_time =
+				session_list[i].connect_start;
+			num_users++;
+		}
+		TALLOC_FREE(machine_name);
+	}
+	TALLOC_FREE(session_list);
+
+	tmp = talloc_realloc(mem_ctx, users, struct dom_usr, num_users);
+	if (tmp == NULL) {
+		return NULL;
+	}
+	users = tmp;
+
+	/* Sort the user list by time, oldest first */
+	qsort(users, num_users, sizeof(struct dom_usr), dom_user_cmp);
+
+	errno = 0;
+	return users;
+}
+
 /*******************************************************************
- Fill in the values for the struct wkssvc_NetWkstaInfo100.
+ RPC Workstation Service request NetWkstaGetInfo with level 100.
+ Returns to the requester:
+  - The machine name.
+  - The smb version number
+  - The domain name.
+ Returns a filled in wkssvc_NetWkstaInfo100 struct.
  ********************************************************************/
 
-static void create_wks_info_100(struct wkssvc_NetWkstaInfo100 *info100)
+static struct wkssvc_NetWkstaInfo100 *create_wks_info_100(TALLOC_CTX *mem_ctx)
 {
+	struct wkssvc_NetWkstaInfo100 *info100;
+
+	info100 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo100);
+	if (info100 == NULL) {
+		return NULL;
+	}
+
 	info100->platform_id	 = PLATFORM_ID_NT;	/* unknown */
 	info100->version_major	 = lp_major_announce_version();
 	info100->version_minor	 = lp_minor_announce_version();
@@ -45,30 +268,130 @@ static void create_wks_info_100(struct wkssvc_NetWkstaInfo100 *info100)
 	info100->domain_name = talloc_asprintf_strupper_m(
 		info100, "%s", lp_workgroup());
 
-	return;
+	return info100;
 }
 
-/********************************************************************
- only supports info level 100 at the moment.
+/*******************************************************************
+ RPC Workstation Service request NetWkstaGetInfo with level 101.
+ Returns to the requester:
+  - As per NetWkstaGetInfo with level 100, plus:
+  - The LANMAN directory path (not currently supported).
+ Returns a filled in wkssvc_NetWkstaInfo101 struct.
  ********************************************************************/
 
-WERROR _wkssvc_NetWkstaGetInfo(pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r)
+static struct wkssvc_NetWkstaInfo101 *create_wks_info_101(TALLOC_CTX *mem_ctx)
 {
-	struct wkssvc_NetWkstaInfo100 *wks100 = NULL;
+	struct wkssvc_NetWkstaInfo101 *info101;
 
-	/* We only support info level 100 currently */
-
-	if ( r->in.level != 100 ) {
-		return WERR_UNKNOWN_LEVEL;
+	info101 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo101);
+	if (info101 == NULL) {
+		return NULL;
 	}
 
-	if ( (wks100 = TALLOC_ZERO_P(p->mem_ctx, struct wkssvc_NetWkstaInfo100)) == NULL ) {
-		return WERR_NOMEM;
+	info101->platform_id	 = PLATFORM_ID_NT;	/* unknown */
+	info101->version_major	 = lp_major_announce_version();
+	info101->version_minor	 = lp_minor_announce_version();
+
+	info101->server_name = talloc_asprintf_strupper_m(
+		info101, "%s", global_myname());
+	info101->domain_name = talloc_asprintf_strupper_m(
+		info101, "%s", lp_workgroup());
+	info101->lan_root = "";
+
+	return info101;
+}
+
+/*******************************************************************
+ RPC Workstation Service request NetWkstaGetInfo with level 102.
+ Returns to the requester:
+  - As per NetWkstaGetInfo with level 101, plus:
+  - The number of logged in users.
+ Returns a filled in wkssvc_NetWkstaInfo102 struct.
+ ********************************************************************/
+
+static struct wkssvc_NetWkstaInfo102 *create_wks_info_102(TALLOC_CTX *mem_ctx)
+{
+	struct wkssvc_NetWkstaInfo102 *info102;
+	char **users;
+
+	info102 = talloc(mem_ctx, struct wkssvc_NetWkstaInfo102);
+	if (info102 == NULL) {
+		return NULL;
 	}
 
-	create_wks_info_100( wks100 );
+	info102->platform_id	 = PLATFORM_ID_NT;	/* unknown */
+	info102->version_major	 = lp_major_announce_version();
+	info102->version_minor	 = lp_minor_announce_version();
+
+	info102->server_name = talloc_asprintf_strupper_m(
+		info102, "%s", global_myname());
+	info102->domain_name = talloc_asprintf_strupper_m(
+		info102, "%s", lp_workgroup());
+	info102->lan_root = "";
 
-	r->out.info->info100 = wks100;
+	users = get_logged_on_userlist(talloc_tos());
+	info102->logged_on_users = talloc_array_length(users);
+
+	TALLOC_FREE(users);
+
+	return info102;
+}
+
+/********************************************************************
+ Handling for RPC Workstation Service request NetWkstaGetInfo
+ ********************************************************************/
+
+WERROR _wkssvc_NetWkstaGetInfo(pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r)
+{
+	switch (r->in.level) {
+	case 100:
+		/* Level 100 can be allowed from anyone including anonymous
+		 * so no access checks are needed for this case */
+		r->out.info->info100 = create_wks_info_100(p->mem_ctx);
+		if (r->out.info->info100 == NULL) {
+			return WERR_NOMEM;
+		}
+		break;
+	case 101:
+		/* Level 101 can be allowed from any logged in user */
+		if (!nt_token_check_sid(&global_sid_Authenticated_Users,
+					p->server_info->ptok)) {
+			DEBUG(1,("User not allowed for NetWkstaGetInfo level "
+				 "101\n"));
+			DEBUGADD(3,(" - does not have sid for Authenticated "
+				    "Users %s:\n",
+				    sid_string_dbg(
+					    &global_sid_Authenticated_Users)));
+			debug_nt_user_token(DBGC_CLASS, 3,
+					    p->server_info->ptok);
+			return WERR_ACCESS_DENIED;
+		}
+		r->out.info->info101 = create_wks_info_101(p->mem_ctx);
+		if (r->out.info->info101 == NULL) {
+			return WERR_NOMEM;
+		}
+		break;
+	case 102:
+		/* Level 102 Should only be allowed from a domain administrator */
+		if (!nt_token_check_sid(&global_sid_Builtin_Administrators,
+					p->server_info->ptok)) {
+			DEBUG(1,("User not allowed for NetWkstaGetInfo level "
+				 "102\n"));
+			DEBUGADD(3,(" - does not have sid for Administrators "
+				    "group %s, sids are:\n",
+				    sid_string_dbg(&global_sid_Builtin_Administrators)));
+			debug_nt_user_token(DBGC_CLASS, 3,
+					    p->server_info->ptok);
+			return WERR_ACCESS_DENIED;
+		}
+		r->out.info->info102 = create_wks_info_102(p->mem_ctx);
+		if (r->out.info->info102 == NULL) {
+			return WERR_NOMEM;
+		}
+		break;
+	default:
+		return WERR_UNKNOWN_LEVEL;
+	}
 
 	return WERR_OK;
 }
@@ -84,13 +407,190 @@ WERROR _wkssvc_NetWkstaSetInfo(pipes_struct *p, struct wkssvc_NetWkstaSetInfo *r
 }
 
 /********************************************************************
+ RPC Workstation Service request NetWkstaEnumUsers with level 0:
+ Returns to the requester:
+  - the user names of the logged in users.
+ Returns a filled in wkssvc_NetWkstaEnumUsersCtr0 struct.
+ ********************************************************************/
+
+static struct wkssvc_NetWkstaEnumUsersCtr0 *create_enum_users0(
+	TALLOC_CTX *mem_ctx)
+{
+	struct wkssvc_NetWkstaEnumUsersCtr0 *ctr0;
+	char **users;
+	int i, num_users;
+
+	ctr0 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr0);
+	if (ctr0 == NULL) {
+		return NULL;
+	}
+
+	users = get_logged_on_userlist(talloc_tos());
+	if (users == NULL && errno != 0) {
+		DEBUG(1,("get_logged_on_userlist error %d: %s\n",
+			errno, strerror(errno)));
+		TALLOC_FREE(ctr0);
+		return NULL;
+	}
+
+	num_users = talloc_array_length(users);
+	ctr0->entries_read = num_users;
+	ctr0->user0 = talloc_array(ctr0, struct wkssvc_NetrWkstaUserInfo0,
+				   num_users);
+	if (ctr0->user0 == NULL) {
+		TALLOC_FREE(ctr0);
+		TALLOC_FREE(users);
+		return NULL;
+	}
+
+	for (i=0; i<num_users; i++) {
+		ctr0->user0[i].user_name = talloc_move(ctr0->user0, &users[i]);
+	}
+	TALLOC_FREE(users);
+	return ctr0;
+}
+
+/********************************************************************
+ RPC Workstation Service request NetWkstaEnumUsers with level 1.
+ Returns to the requester:
+  - the user names of the logged in users,
+  - the domain or machine each is logged into,
+  - the password server that was used to authenticate each,
+  - other domains each user is logged into (not currently supported).
+ Returns a filled in wkssvc_NetWkstaEnumUsersCtr1 struct.
+ ********************************************************************/
+
+static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1(
+	TALLOC_CTX *mem_ctx)
+{
+	struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1;
+	char **users;
+	struct dom_usr *dom_users;
+	const char *pwd_server;
+	char *pwd_tmp;
+	int i, j, num_users, num_dom_users;
+
+	ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1);
+	if (ctr1 == NULL) {
+		return NULL;
+	}
+
+	users = get_logged_on_userlist(talloc_tos());
+	if (users == NULL && errno != 0) {
+		DEBUG(1,("get_logged_on_userlist error %d: %s\n",
+			errno, strerror(errno)));
+		TALLOC_FREE(ctr1);
+		return NULL;
+	}
+	num_users = talloc_array_length(users);
+
+	dom_users = get_domain_userlist(talloc_tos());
+	if (dom_users == NULL && errno != 0) {
+		TALLOC_FREE(ctr1);
+		TALLOC_FREE(users);
+		return NULL;
+	}
+	num_dom_users = talloc_array_length(dom_users);
+
+	ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1,
+				   num_users+num_dom_users);
+	if (ctr1->user1 == NULL) {
+		TALLOC_FREE(ctr1);
+		TALLOC_FREE(users);
+		TALLOC_FREE(dom_users);
+		return NULL;
+	}
+
+	pwd_server = "";
+
+	if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_passwordserver()))) {


-- 
Samba Shared Repository


More information about the samba-cvs mailing list