[SCM] Samba Shared Repository - branch v3-4-test updated - release-4-0-0alpha7-1113-g747068f

Karolin Seeger kseeger at samba.org
Wed Jun 3 07:56:33 GMT 2009


The branch, v3-4-test has been updated
       via  747068ff4688000287ace009f3dc58e12eefa615 (commit)
       via  7086d3164cb897adb23e753294ca78bdfe01d4a5 (commit)
       via  138b037c437ad27466646beb33e1922b6d18ef8c (commit)
       via  8191fe96c6a5ba57ffc94d7cc54693d6eb2967f5 (commit)
       via  291a3e79ba26b1c0e00bf929337d6251c8929e05 (commit)
      from  36b8bbb0328bbcccdc6e9fe99ae4933c916885da (commit)

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


- Log -----------------------------------------------------------------
commit 747068ff4688000287ace009f3dc58e12eefa615
Author: Simo Sorce <idra at samba.org>
Date:   Sat May 30 10:16:31 2009 -0400

    Make it possible to change machine account sids
    
    Fixes bug #6081
    (cherry picked from commit 9fc13f6a2d02c22f639a1a819e09ebb648faaff7)

commit 7086d3164cb897adb23e753294ca78bdfe01d4a5
Author: Simo Sorce <idra at samba.org>
Date:   Sat May 16 18:10:39 2009 -0400

    Consolidate user create/delete paths in smbpasswd
    
    This patch changes the way smbpasswd behaves when adding/deleting users.
    smbpasswd now calls pdb_create_user/pdb_delete_user, this means that if
    add/delete user scripts are configured then they are used to create or
    delete unix users as well. If the scripts are not defined the behavioris
    unchanged.
    This also allow to use smbpasswd -a/-x with ldapsam:editposix to allow
    automatic creation/deletion of users.
    
    Part 2/2 for bug #6333.
    
    Signed-off-by: Günther Deschner <gd at samba.org>
    (cherry picked from commit 64d1b5c4e1efd734176c1ea6e5e564e626128b4f)

commit 138b037c437ad27466646beb33e1922b6d18ef8c
Author: Michael Adam <obnox at samba.org>
Date:   Fri May 29 23:48:26 2009 +0200

    s3:pdbedit: fix "format not a string literal and no format arguments" warnings
    
    Michael
    (cherry picked from commit 2b68fb7cb4ab5b76028c54ef163badd2952fe0c0)

commit 8191fe96c6a5ba57ffc94d7cc54693d6eb2967f5
Author: Simo Sorce <idra at samba.org>
Date:   Sat May 16 20:36:28 2009 -0400

    Consolidate create/delete account paths in pdbedit
    
    Use common paths like for smbpasswd, so that all utilities
    behave the same way. As for smbpasswd this changes the behavior
    of pdbedit to create/delete unix users is the add/delete user
    scripts are provided, or ldapsam:editposix is configured.
    
    Part 1/2 for bug #6333.
    
    Signed-off-by: Günther Deschner <gd at samba.org>
    (cherry picked from commit f48e39540c9767e9077e7534a6d410b4ce597c86)

commit 291a3e79ba26b1c0e00bf929337d6251c8929e05
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Apr 5 17:01:57 2009 +0200

    Remove a silly check
    
    This does not increase security, and if later error messages suck, we have to
    fix those.
    (cherry picked from commit e5c7df34f2d461b0f348fc1b40275a97d918ed9e)

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

Summary of changes:
 source3/include/proto.h   |    2 +-
 source3/param/loadparm.c  |    5 +
 source3/passdb/passdb.c   |  326 +++++++++++---------
 source3/utils/pdbedit.c   |  722 ++++++++++++++++++++++++++++-----------------
 source3/utils/smbpasswd.c |   42 +--
 5 files changed, 654 insertions(+), 443 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/proto.h b/source3/include/proto.h
index a7ef216..b5c0608 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -4353,7 +4353,7 @@ enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp);
 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val);
 int lp_min_receive_file_size(void);
 char* lp_perfcount_module(void);
-
+void lp_set_passdb_backend(const char *backend);
 
 /* The following definitions come from param/util.c  */
 
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index faffb8e..553938f 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -9736,3 +9736,8 @@ const char *lp_socket_address(void)
 	}
 	return  Globals.szSocketAddress;
 }
+
+void lp_set_passdb_backend(const char *backend)
+{
+	string_set(&Globals.szPassdbBackend, backend);
+}
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index fd715d2..3ab0a1d 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -626,7 +626,14 @@ bool lookup_global_sam_name(const char *name, int flags, uint32_t *rid,
 }
 
 /*************************************************************
- Change a password entry in the local smbpasswd file.
+ Change a password entry in the local passdb backend.
+
+ Assumptions:
+  - always called as root
+  - ignores the account type except when adding a new account
+  - will create/delete the unix account if the relative
+    add/delete user script is configured
+
  *************************************************************/
 
 NTSTATUS local_password_change(const char *user_name,
@@ -635,133 +642,135 @@ NTSTATUS local_password_change(const char *user_name,
 				char **pp_err_str,
 				char **pp_msg_str)
 {
-	struct samu *sam_pass=NULL;
-	uint32 other_acb;
+	TALLOC_CTX *tosctx;
+	struct samu *sam_pass;
+	uint32_t acb;
+	uint32_t rid;
 	NTSTATUS result;
+	bool user_exists;
+	int ret;
 
 	*pp_err_str = NULL;
 	*pp_msg_str = NULL;
 
-	/* Get the smb passwd entry for this user */
-
-	if ( !(sam_pass = samu_new( NULL )) ) {
+	tosctx = talloc_tos();
+	if (!tosctx) {
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	become_root();
-	if(!pdb_getsampwnam(sam_pass, user_name)) {
-		unbecome_root();
-		TALLOC_FREE(sam_pass);
-
-		if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
-			int tmp_debug = DEBUGLEVEL;
-			struct passwd *pwd;
-
-			/* Might not exist in /etc/passwd. */
-
-			if (tmp_debug < 1) {
-				DEBUGLEVEL = 1;
-			}
+	sam_pass = samu_new(tosctx);
+	if (!sam_pass) {
+		result = NT_STATUS_NO_MEMORY;
+		goto done;
+	}
 
-			if ( !(pwd = getpwnam_alloc(talloc_autofree_context(), user_name)) ) {
-				return NT_STATUS_NO_SUCH_USER;
+	/* Get the smb passwd entry for this user */
+	user_exists = pdb_getsampwnam(sam_pass, user_name);
+
+	/* Check delete first, we don't need to do anything else if we
+	 * are going to delete the acocunt */
+	if (user_exists && (local_flags & LOCAL_DELETE_USER)) {
+
+		result = pdb_delete_user(tosctx, sam_pass);
+		if (!NT_STATUS_IS_OK(result)) {
+			ret = asprintf(pp_err_str,
+					"Failed to delete entry for user %s.\n",
+					user_name);
+			if (ret < 0) {
+				*pp_err_str = NULL;
 			}
-
-			/* create the struct samu and initialize the basic Unix properties */
-
-			if ( !(sam_pass = samu_new( NULL )) ) {
-				return NT_STATUS_NO_MEMORY;
+			result = NT_STATUS_UNSUCCESSFUL;
+		} else {
+			ret = asprintf(pp_msg_str,
+					"Deleted user %s.\n",
+					user_name);
+			if (ret < 0) {
+				*pp_msg_str = NULL;
 			}
+		}
+		goto done;
+	}
 
-			result = samu_set_unix( sam_pass, pwd );
-
-			DEBUGLEVEL = tmp_debug;
+	if (user_exists && (local_flags & LOCAL_ADD_USER)) {
+		/* the entry already existed */
+		local_flags &= ~LOCAL_ADD_USER;
+	}
 
-			TALLOC_FREE( pwd );
+	if (!user_exists && !(local_flags & LOCAL_ADD_USER)) {
+		ret = asprintf(pp_err_str,
+				"Failed to find entry for user %s.\n",
+				user_name);
+		if (ret < 0) {
+			*pp_err_str = NULL;
+		}
+		result = NT_STATUS_NO_SUCH_USER;
+		goto done;
+	}
 
-			if (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PRIMARY_GROUP)) {
-				return result;
-			}
+	/* First thing add the new user if we are required to do so */
+	if (local_flags & LOCAL_ADD_USER) {
 
-			if (!NT_STATUS_IS_OK(result)) {
-				if (asprintf(pp_err_str, "Failed to " "initialize account for user %s: %s\n",
-						user_name, nt_errstr(result)) < 0) {
-					*pp_err_str = NULL;
-				}
-				return result;
-			}
+		if (local_flags & LOCAL_TRUST_ACCOUNT) {
+			acb = ACB_WSTRUST;
+		} else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
+			acb = ACB_DOMTRUST;
 		} else {
-			if (asprintf(pp_err_str, "Failed to find entry for user %s.\n", user_name) < 0) {
-				*pp_err_str = NULL;
-			}
-			return NT_STATUS_NO_SUCH_USER;
+			acb = ACB_NORMAL;
 		}
-	} else {
-		unbecome_root();
-		/* the entry already existed */
-		local_flags &= ~LOCAL_ADD_USER;
-	}
 
-	/* the 'other' acb bits not being changed here */
-	other_acb =  (pdb_get_acct_ctrl(sam_pass) & (~(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL)));
-	if (local_flags & LOCAL_TRUST_ACCOUNT) {
-		if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
-			if (asprintf(pp_err_str, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name) < 0) {
+		result = pdb_create_user(tosctx, user_name, acb, &rid);
+		if (!NT_STATUS_IS_OK(result)) {
+			ret = asprintf(pp_err_str,
+					"Failed to add entry for user %s.\n",
+					user_name);
+			if (ret < 0) {
 				*pp_err_str = NULL;
 			}
-			TALLOC_FREE(sam_pass);
-			return NT_STATUS_UNSUCCESSFUL;
+			result = NT_STATUS_UNSUCCESSFUL;
+			goto done;
 		}
-	} else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
-		if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
-			if (asprintf(pp_err_str, "Failed to set 'domain trust account' flags for user %s.\n", user_name) < 0) {
-				*pp_err_str = NULL;
-			}
-			TALLOC_FREE(sam_pass);
-			return NT_STATUS_UNSUCCESSFUL;
+
+		sam_pass = samu_new(tosctx);
+		if (!sam_pass) {
+			result = NT_STATUS_NO_MEMORY;
+			goto done;
 		}
-	} else {
-		if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
-			if (asprintf(pp_err_str, "Failed to set 'normal account' flags for user %s.\n", user_name) < 0) {
+
+		/* Now get back the smb passwd entry for this new user */
+		user_exists = pdb_getsampwnam(sam_pass, user_name);
+		if (!user_exists) {
+			ret = asprintf(pp_err_str,
+					"Failed to add entry for user %s.\n",
+					user_name);
+			if (ret < 0) {
 				*pp_err_str = NULL;
 			}
-			TALLOC_FREE(sam_pass);
-			return NT_STATUS_UNSUCCESSFUL;
+			result = NT_STATUS_UNSUCCESSFUL;
+			goto done;
 		}
 	}
 
+	acb = pdb_get_acct_ctrl(sam_pass);
+
 	/*
 	 * We are root - just write the new password
 	 * and the valid last change time.
 	 */
-
-	if (local_flags & LOCAL_DISABLE_USER) {
-		if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
-			if (asprintf(pp_err_str, "Failed to set 'disabled' flag for user %s.\n", user_name) < 0) {
-				*pp_err_str = NULL;
-			}
-			TALLOC_FREE(sam_pass);
-			return NT_STATUS_UNSUCCESSFUL;
-		}
-	} else if (local_flags & LOCAL_ENABLE_USER) {
-		if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
-			if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) {
+	if ((local_flags & LOCAL_SET_NO_PASSWORD) && !(acb & ACB_PWNOTREQ)) {
+		acb |= ACB_PWNOTREQ;
+		if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
+			ret = asprintf(pp_err_str,
+					"Failed to set 'no password required' "
+					"flag for user %s.\n", user_name);
+			if (ret < 0) {
 				*pp_err_str = NULL;
 			}
-			TALLOC_FREE(sam_pass);
-			return NT_STATUS_UNSUCCESSFUL;
+			result = NT_STATUS_UNSUCCESSFUL;
+			goto done;
 		}
 	}
 
-	if (local_flags & LOCAL_SET_NO_PASSWORD) {
-		if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
-			if (asprintf(pp_err_str, "Failed to set 'no password required' flag for user %s.\n", user_name) < 0) {
-				*pp_err_str = NULL;
-			}
-			TALLOC_FREE(sam_pass);
-			return NT_STATUS_UNSUCCESSFUL;
-		}
-	} else if (local_flags & LOCAL_SET_PASSWORD) {
+	if (local_flags & LOCAL_SET_PASSWORD) {
 		/*
 		 * If we're dealing with setting a completely empty user account
 		 * ie. One with a password of 'XXXX', but not set disabled (like
@@ -771,83 +780,106 @@ NTSTATUS local_password_change(const char *user_name,
 		 * and the decision hasn't really been made to disable them (ie.
 		 * don't create them disabled). JRA.
 		 */
-		if ((pdb_get_lanman_passwd(sam_pass)==NULL) && (pdb_get_acct_ctrl(sam_pass)&ACB_DISABLED)) {
-			if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
-				if (asprintf(pp_err_str, "Failed to unset 'disabled' flag for user %s.\n", user_name) < 0) {
+		if ((pdb_get_lanman_passwd(sam_pass) == NULL) &&
+		    (acb & ACB_DISABLED)) {
+			acb &= (~ACB_DISABLED);
+			if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
+				ret = asprintf(pp_err_str,
+						"Failed to unset 'disabled' "
+						"flag for user %s.\n",
+						user_name);
+				if (ret < 0) {
 					*pp_err_str = NULL;
 				}
-				TALLOC_FREE(sam_pass);
-				return NT_STATUS_UNSUCCESSFUL;
-			}
-		}
-		if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
-			if (asprintf(pp_err_str, "Failed to unset 'no password required' flag for user %s.\n", user_name) < 0) {
-				*pp_err_str = NULL;
+				result = NT_STATUS_UNSUCCESSFUL;
+				goto done;
 			}
-			TALLOC_FREE(sam_pass);
-			return NT_STATUS_UNSUCCESSFUL;
 		}
 
-		if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
-			if (asprintf(pp_err_str, "Failed to set password for user %s.\n", user_name) < 0) {
+		acb &= (~ACB_PWNOTREQ);
+		if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
+			ret = asprintf(pp_err_str,
+					"Failed to unset 'no password required'"
+					" flag for user %s.\n", user_name);
+			if (ret < 0) {
 				*pp_err_str = NULL;
 			}
-			TALLOC_FREE(sam_pass);
-			return NT_STATUS_UNSUCCESSFUL;
+			result = NT_STATUS_UNSUCCESSFUL;
+			goto done;
 		}
-	}	
 
-	if (local_flags & LOCAL_ADD_USER) {
-		if (NT_STATUS_IS_OK(pdb_add_sam_account(sam_pass))) {
-			if (asprintf(pp_msg_str, "Added user %s.\n", user_name) < 0) {
-				*pp_msg_str = NULL;
-			}
-			TALLOC_FREE(sam_pass);
-			return NT_STATUS_OK;
-		} else {
-			if (asprintf(pp_err_str, "Failed to add entry for user %s.\n", user_name) < 0) {
+		if (!pdb_set_plaintext_passwd(sam_pass, new_passwd)) {
+			ret = asprintf(pp_err_str,
+					"Failed to set password for "
+					"user %s.\n", user_name);
+				if (ret < 0) {
 				*pp_err_str = NULL;
 			}
-			TALLOC_FREE(sam_pass);
-			return NT_STATUS_UNSUCCESSFUL;
+			result = NT_STATUS_UNSUCCESSFUL;
+			goto done;
 		}
-	} else if (local_flags & LOCAL_DELETE_USER) {
-		if (!NT_STATUS_IS_OK(pdb_delete_sam_account(sam_pass))) {
-			if (asprintf(pp_err_str, "Failed to delete entry for user %s.\n", user_name) < 0) {
+	}
+
+	if ((local_flags & LOCAL_DISABLE_USER) && !(acb & ACB_DISABLED)) {
+		acb |= ACB_DISABLED;
+		if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
+			ret = asprintf(pp_err_str,
+					"Failed to set 'disabled' flag for "
+					"user %s.\n", user_name);
+			if (ret < 0) {
 				*pp_err_str = NULL;
 			}
-			TALLOC_FREE(sam_pass);
-			return NT_STATUS_UNSUCCESSFUL;
-		}
-		if (asprintf(pp_msg_str, "Deleted user %s.\n", user_name) < 0) {
-			*pp_msg_str = NULL;
+			result = NT_STATUS_UNSUCCESSFUL;
+			goto done;
 		}
-	} else {
-		result = pdb_update_sam_account(sam_pass);
-		if(!NT_STATUS_IS_OK(result)) {
-			if (asprintf(pp_err_str, "Failed to modify entry for user %s.\n", user_name) < 0) {
+	}
+
+	if ((local_flags & LOCAL_ENABLE_USER) && (acb & ACB_DISABLED)) {
+		acb &= (~ACB_DISABLED);
+		if (!pdb_set_acct_ctrl(sam_pass, acb, PDB_CHANGED)) {
+			ret = asprintf(pp_err_str,
+					"Failed to unset 'disabled' flag for "
+					"user %s.\n", user_name);
+			if (ret < 0) {
 				*pp_err_str = NULL;
 			}
-			TALLOC_FREE(sam_pass);
-			return result;
+			result = NT_STATUS_UNSUCCESSFUL;
+			goto done;
 		}
-		if(local_flags & LOCAL_DISABLE_USER) {
-			if (asprintf(pp_msg_str, "Disabled user %s.\n", user_name) < 0) {
-				*pp_msg_str = NULL;
-			}
-		} else if (local_flags & LOCAL_ENABLE_USER) {
-			if (asprintf(pp_msg_str, "Enabled user %s.\n", user_name) < 0) {
-				*pp_msg_str = NULL;
-			}
-		} else if (local_flags & LOCAL_SET_NO_PASSWORD) {
-			if (asprintf(pp_msg_str, "User %s password set to none.\n", user_name) < 0) {
-				*pp_msg_str = NULL;
-			}
+	}
+
+	/* now commit changes if any */
+	result = pdb_update_sam_account(sam_pass);
+	if (!NT_STATUS_IS_OK(result)) {
+		ret = asprintf(pp_err_str,
+				"Failed to modify entry for user %s.\n",
+				user_name);
+		if (ret < 0) {
+			*pp_err_str = NULL;
 		}
+		goto done;
+	}
+
+	if (local_flags & LOCAL_ADD_USER) {
+		ret = asprintf(pp_msg_str, "Added user %s.\n", user_name);
+	} else if (local_flags & LOCAL_DISABLE_USER) {
+		ret = asprintf(pp_msg_str, "Disabled user %s.\n", user_name);
+	} else if (local_flags & LOCAL_ENABLE_USER) {
+		ret = asprintf(pp_msg_str, "Enabled user %s.\n", user_name);
+	} else if (local_flags & LOCAL_SET_NO_PASSWORD) {
+		ret = asprintf(pp_msg_str,
+				"User %s password set to none.\n", user_name);
 	}
 
+	if (ret < 0) {
+		*pp_msg_str = NULL;
+	}
+
+	result = NT_STATUS_OK;
+
+done:
 	TALLOC_FREE(sam_pass);
-	return NT_STATUS_OK;
+	return result;
 }
 
 /**********************************************************************
diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c
index a5bc0c9..ca4011a 100644
--- a/source3/utils/pdbedit.c
+++ b/source3/utils/pdbedit.c
@@ -53,6 +53,26 @@
 #define MASK_ALWAYS_GOOD	0x0000001F
 #define MASK_USER_GOOD		0x00405FE0
 
+static int get_sid_from_cli_string(DOM_SID *sid, const char *str_sid)
+{
+	uint32_t rid;
+
+	if (!string_to_sid(sid, str_sid)) {
+		/* not a complete sid, may be a RID,
+		 * try building a SID */
+
+		if (sscanf(str_sid, "%u", &rid) != 1) {
+			fprintf(stderr, "Error passed string is not "
+					"a complete SID or RID!\n");
+			return -1;
+		}
+		sid_copy(sid, get_global_sam_sid());
+		sid_append_rid(sid, rid);
+	}
+
+	return 0;
+}
+
 /*********************************************************
  Add all currently available users to another db
  ********************************************************/
@@ -321,167 +341,186 @@ static int print_sam_info (struct samu *sam_pwent, bool verbosity, bool smbpwdst
  Get an Print User Info
 **********************************************************/
 
-static int print_user_info (struct pdb_methods *in, const char *username, bool verbosity, bool smbpwdstyle)
+static int print_user_info(const char *username,
+			   bool verbosity, bool smbpwdstyle)
 {
-	struct samu *sam_pwent=NULL;
-	bool ret;
+	struct samu *sam_pwent = NULL;
+	bool bret;
+	int ret;
 
-	if ( (sam_pwent = samu_new( NULL )) == NULL ) {
+	sam_pwent = samu_new(NULL);
+	if (!sam_pwent) {
 		return -1;
 	}
 
-	ret = NT_STATUS_IS_OK(in->getsampwnam (in, sam_pwent, username));
-
-	if (ret==False) {
+	bret = pdb_getsampwnam(sam_pwent, username);
+	if (!bret) {
 		fprintf (stderr, "Username not found!\n");
 		TALLOC_FREE(sam_pwent);
 		return -1;
 	}
 
-	ret=print_sam_info (sam_pwent, verbosity, smbpwdstyle);
+	ret = print_sam_info(sam_pwent, verbosity, smbpwdstyle);
+
 	TALLOC_FREE(sam_pwent);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list