[SCM] Samba Shared Repository - branch master updated

Volker Lendecke vlendec at samba.org
Sun Dec 6 05:07:43 MST 2009


The branch, master has been updated
       via  da8b405... s3: Fix a const discard warning
       via  3b8e85d... s3: talloc_array_length deals file with a NULL argument
       via  1ba91c0... s3: Small simplification: qsort deals fine with just one entry
       via  449045e... s3: Simplify usr_info_cmp by calling timeval_compare()
       via  aef303f... s3: Add rpcclient wkssvc_enumerateusers
       via  bbffd79... s3: Complete support for NetWkstaGetInfo/NetWkstaEnumUsers
       via  7eaff9b... s3: First cut at _wkssvc_NetWkstaEnumUsers
       via  a902c4c... s3: Support NetWkstaGetInfo 101 and 102
      from  9b265a6... s4-ldif: Fix memory leek in ldb_ldif_write()

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


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

    s3: Fix a const discard warning

commit 3b8e85d68f11321988232ff4cfea481cc0862b2d
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 1ba91c0a51e173bbf6616b2bb4ea778acd0c5dc8
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 449045e75d7920b7bb20f8445aadff783ddbfd0c
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 aef303f83c2bdebbd3bf64d8c3ed4b2621232ccb
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Dec 6 12:40:44 2009 +0100

    s3: Add rpcclient wkssvc_enumerateusers

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

    s3: Complete support for NetWkstaGetInfo/NetWkstaEnumUsers

commit 7eaff9b300ff290b6054afdab51343ca0948a521
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 a902c4cc50b8e7d0bdcc334fe63c1818f7cf4347
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 16fbf88..169e01d 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -2272,7 +2272,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