Index: trunk/server/WHATSNEW.txt
===================================================================
--- trunk/server/WHATSNEW.txt	(revision 604)
+++ trunk/server/WHATSNEW.txt	(revision 617)
@@ -1,2 +1,60 @@
+                   ==============================
+                   Release Notes for Samba 3.5.10
+			   July 26, 2011
+                   ==============================
+
+
+This is a security release in order to address
+CVE-2011-2522 (Cross-Site Request Forgery in SWAT) and
+CVE-2011-2694 (Cross-Site Scripting vulnerability in SWAT).
+
+
+o  CVE-2011-2522:
+   The Samba Web Administration Tool (SWAT) in Samba versions
+   3.0.x to 3.5.9 are affected by a cross-site request forgery.
+
+
+o  CVE-2011-2694:
+   The Samba Web Administration Tool (SWAT) in Samba versions
+   3.0.x to 3.5.9 are affected by a cross-site scripting
+   vulnerability.
+
+Please note that SWAT must be enabled in order for these
+vulnerabilities to be exploitable. By default, SWAT
+is *not* enabled on a Samba install.
+
+
+Changes since 3.5.9:
+--------------------
+
+
+o   Kai Blin <kai@samba.org>
+    * BUG 8289: SWAT contains a cross-site scripting vulnerability.
+    * BUG 8290: CSRF vulnerability in SWAT.
+
+
+######################################################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical IRC channel on irc.freenode.net.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored.  All bug reports should
+be filed under the Samba 3.5 product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+Release notes for older releases follow:
+----------------------------------------
+
                    =============================
                    Release Notes for Samba 3.5.9
@@ -143,6 +201,6 @@
 
 
-Release notes for older releases follow:
-----------------------------------------
+----------------------------------------------------------------------
+
 
                    =============================
Index: trunk/server/packaging/RHEL-CTDB/samba.spec
===================================================================
--- trunk/server/packaging/RHEL-CTDB/samba.spec	(revision 604)
+++ trunk/server/packaging/RHEL-CTDB/samba.spec	(revision 617)
@@ -6,5 +6,5 @@
 Packager: Samba Team <samba@samba.org>
 Name:         samba
-Version:      3.5.9
+Version:      3.5.10
 Release:      1GITHASH
 Epoch:        0
Index: trunk/server/packaging/RHEL/makerpms.sh
===================================================================
--- trunk/server/packaging/RHEL/makerpms.sh	(revision 604)
+++ trunk/server/packaging/RHEL/makerpms.sh	(revision 617)
@@ -21,5 +21,5 @@
 USERID=`id -u`
 GRPID=`id -g`
-VERSION='3.5.9'
+VERSION='3.5.10'
 REVISION=''
 SPECFILE="samba.spec"
Index: trunk/server/packaging/RHEL/samba.spec
===================================================================
--- trunk/server/packaging/RHEL/samba.spec	(revision 604)
+++ trunk/server/packaging/RHEL/samba.spec	(revision 617)
@@ -6,5 +6,5 @@
 Packager: Samba Team <samba@samba.org>
 Name:         samba
-Version:      3.5.9
+Version:      3.5.10
 Release:      1
 Epoch:        0
Index: trunk/server/source3/VERSION
===================================================================
--- trunk/server/source3/VERSION	(revision 604)
+++ trunk/server/source3/VERSION	(revision 617)
@@ -26,5 +26,5 @@
 SAMBA_VERSION_MAJOR=3
 SAMBA_VERSION_MINOR=5
-SAMBA_VERSION_RELEASE=9
+SAMBA_VERSION_RELEASE=10
 
 ########################################################
Index: trunk/server/source3/web/cgi.c
===================================================================
--- trunk/server/source3/web/cgi.c	(revision 604)
+++ trunk/server/source3/web/cgi.c	(revision 617)
@@ -20,4 +20,6 @@
 #include "includes.h"
 #include "web/swat_proto.h"
+#include "secrets.h"
+#include "../lib/util/util.h"
 
 #define MAX_VARIABLES 10000
@@ -43,4 +45,5 @@
 static char *pathinfo;
 static char *C_user;
+static char *C_pass;
 static bool inetd_server;
 static bool got_request;
@@ -323,5 +326,21 @@
 	}
 
-	setuid(0);
+	C_user = SMB_STRDUP(user);
+
+	if (!setuid(0)) {
+		C_pass = secrets_fetch_generic("root", "SWAT");
+		if (C_pass == NULL) {
+			char *tmp_pass = NULL;
+			tmp_pass = generate_random_str(talloc_tos(), 16);
+			if (tmp_pass == NULL) {
+				printf("%sFailed to create random nonce for "
+				       "SWAT session\n<br>%s\n", head, tail);
+				exit(0);
+			}
+			secrets_store_generic("root", "SWAT", tmp_pass);
+			C_pass = SMB_STRDUP(tmp_pass);
+			TALLOC_FREE(tmp_pass);
+		}
+	}
 	setuid(pwd->pw_uid);
 	if (geteuid() != pwd->pw_uid || getuid() != pwd->pw_uid) {
@@ -392,4 +411,5 @@
 			/* Save the users name */
 			C_user = SMB_STRDUP(user);
+			C_pass = SMB_STRDUP(user_pass);
 			TALLOC_FREE(pass);
 			return True;
@@ -426,4 +446,11 @@
 }
 
+/***************************************************************************
+return a ptr to the users password
+  ***************************************************************************/
+char *cgi_user_pass(void)
+{
+        return(C_pass);
+}
 
 /***************************************************************************
Index: trunk/server/source3/web/statuspage.c
===================================================================
--- trunk/server/source3/web/statuspage.c	(revision 604)
+++ trunk/server/source3/web/statuspage.c	(revision 617)
@@ -248,6 +248,11 @@
 	bool waitup = False;
 	TALLOC_CTX *ctx = talloc_stackframe();
+	const char form_name[] = "status";
 
 	smbd_pid = pid_to_procid(pidfile_pid("smbd"));
+
+	if (!verify_xsrf_token(form_name)) {
+		goto output_page;
+	}
 
 	if (cgi_variable("smbd_restart") || cgi_variable("all_restart")) {
@@ -327,7 +332,9 @@
 	initPid2Machine ();
 
+output_page:
 	printf("<H2>%s</H2>\n", _("Server Status"));
 
 	printf("<FORM method=post>\n");
+	print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
 
 	if (!autorefresh) {
Index: trunk/server/source3/web/swat.c
===================================================================
--- trunk/server/source3/web/swat.c	(revision 604)
+++ trunk/server/source3/web/swat.c	(revision 617)
@@ -30,4 +30,5 @@
 #include "includes.h"
 #include "web/swat_proto.h"
+#include "../lib/crypto/md5.h"
 
 static int demo_mode = False;
@@ -51,4 +52,7 @@
 #define ENABLE_USER_FLAG "enable_user_flag"
 #define RHOST "remote_host"
+#define XSRF_TOKEN "xsrf"
+#define XSRF_TIME "xsrf_time"
+#define XSRF_TIMEOUT 300
 
 #define _(x) lang_msg_rotate(talloc_tos(),x)
@@ -138,4 +142,74 @@
 	return parmname;
 }
+
+void get_xsrf_token(const char *username, const char *pass,
+		    const char *formname, time_t xsrf_time, char token_str[33])
+{
+	struct MD5Context md5_ctx;
+	uint8_t token[16];
+	int i;
+
+	token_str[0] = '\0';
+	ZERO_STRUCT(md5_ctx);
+	MD5Init(&md5_ctx);
+
+	MD5Update(&md5_ctx, (uint8_t *)formname, strlen(formname));
+	MD5Update(&md5_ctx, (uint8_t *)&xsrf_time, sizeof(time_t));
+	if (username != NULL) {
+		MD5Update(&md5_ctx, (uint8_t *)username, strlen(username));
+	}
+	if (pass != NULL) {
+		MD5Update(&md5_ctx, (uint8_t *)pass, strlen(pass));
+	}
+
+	MD5Final(token, &md5_ctx);
+
+	for(i = 0; i < sizeof(token); i++) {
+		char tmp[3];
+
+		snprintf(tmp, sizeof(tmp), "%02x", token[i]);
+		strncat(token_str, tmp, sizeof(tmp));
+	}
+}
+
+void print_xsrf_token(const char *username, const char *pass,
+		      const char *formname)
+{
+	char token[33];
+	time_t xsrf_time = time(NULL);
+
+	get_xsrf_token(username, pass, formname, xsrf_time, token);
+	printf("<input type=\"hidden\" name=\"%s\" value=\"%s\">\n",
+	       XSRF_TOKEN, token);
+	printf("<input type=\"hidden\" name=\"%s\" value=\"%lld\">\n",
+	       XSRF_TIME, (long long int)xsrf_time);
+}
+
+bool verify_xsrf_token(const char *formname)
+{
+	char expected[33];
+	const char *username = cgi_user_name();
+	const char *pass = cgi_user_pass();
+	const char *token = cgi_variable_nonull(XSRF_TOKEN);
+	const char *time_str = cgi_variable_nonull(XSRF_TIME);
+	time_t xsrf_time = 0;
+	time_t now = time(NULL);
+
+	if (sizeof(time_t) == sizeof(int)) {
+		xsrf_time = atoi(time_str);
+	} else if (sizeof(time_t) == sizeof(long)) {
+		xsrf_time = atol(time_str);
+	} else if (sizeof(time_t) == sizeof(long long)) {
+		xsrf_time = atoll(time_str);
+	}
+
+	if (abs(now - xsrf_time) > XSRF_TIMEOUT) {
+		return false;
+	}
+
+	get_xsrf_token(username, pass, formname, xsrf_time, expected);
+	return (strncmp(expected, token, sizeof(expected)) == 0);
+}
+
 
 /****************************************************************************
@@ -612,4 +686,9 @@
 {
 	int full_view=0;
+	const char form_name[] = "viewconfig";
+
+	if (!verify_xsrf_token(form_name)) {
+		goto output_page;
+	}
 
 	if (cgi_variable("full_view")) {
@@ -617,6 +696,8 @@
 	}
 
+output_page:
 	printf("<H2>%s</H2>\n", _("Current Config"));
 	printf("<form method=post>\n");
+	print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
 
 	if (full_view) {
@@ -638,4 +719,5 @@
 {
 	unsigned int parm_filter = FLAG_WIZARD;
+	const char form_name[] = "wizard_params";
 
 	/* Here we first set and commit all the parameters that were selected
@@ -643,4 +725,8 @@
 
 	printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page"));
+
+	if (!verify_xsrf_token(form_name)) {
+		goto output_page;
+	}
 
 	if (cgi_variable("Commit")) {
@@ -649,5 +735,7 @@
 	}
 
+output_page:
 	printf("<form name=\"swatform\" method=post action=wizard_params>\n");
+	print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
 
 	if (have_write_access) {
@@ -685,4 +773,9 @@
 	int HomeExpo = 0;
 	int SerType = 0;
+	const char form_name[] = "wizard";
+
+	if (!verify_xsrf_token(form_name)) {
+		goto output_page;
+	}
 
 	if (cgi_variable("Rewrite")) {
@@ -775,8 +868,10 @@
 
 	role = lp_server_role();
-	
+
+output_page:
 	/* Here we go ... */
 	printf("<H2>%s</H2>\n", _("Samba Configuration Wizard"));
 	printf("<form method=post action=wizard>\n");
+	print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
 
 	if (have_write_access) {
@@ -847,6 +942,11 @@
 	unsigned int parm_filter = FLAG_BASIC;
 	int mode = 0;
+	const char form_name[] = "globals";
 
 	printf("<H2>%s</H2>\n", _("Global Parameters"));
+
+	if (!verify_xsrf_token(form_name)) {
+		goto output_page;
+	}
 
 	if (cgi_variable("Commit")) {
@@ -862,5 +962,7 @@
 		mode = 1;
 
+output_page:
 	printf("<form name=\"swatform\" method=post action=globals>\n");
+	print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
 
 	ViewModeBoxes( mode );
@@ -902,9 +1004,15 @@
 	unsigned int parm_filter = FLAG_BASIC;
 	size_t converted_size;
+	const char form_name[] = "shares";
+
+	printf("<H2>%s</H2>\n", _("Share Parameters"));
+
+	if (!verify_xsrf_token(form_name)) {
+		goto output_page;
+	}
 
 	if (share)
 		snum = lp_servicenumber(share);
 
-	printf("<H2>%s</H2>\n", _("Share Parameters"));
 
 	if (cgi_variable("Commit") && snum >= 0) {
@@ -932,8 +1040,4 @@
 	}
 
-	printf("<FORM name=\"swatform\" method=post>\n");
-
-	printf("<table>\n");
-
 	if ( cgi_variable("ViewMode") )
 		mode = atoi(cgi_variable_nonull("ViewMode"));
@@ -942,4 +1046,10 @@
 	if ( cgi_variable("AdvMode"))
 		mode = 1;
+
+output_page:
+	printf("<FORM name=\"swatform\" method=post>\n");
+	print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
+
+	printf("<table>\n");
 
 	ViewModeBoxes( mode );
@@ -1122,9 +1232,7 @@
 		printf("<p>");
 		if (rslt == True) {
-			printf(_(" The passwd for '%s' has been changed."), cgi_variable_nonull(SWAT_USER));
-			printf("\n");
+			printf("%s\n", _(" The passwd has been changed."));
 		} else {
-			printf(_(" The passwd for '%s' has NOT been changed."), cgi_variable_nonull(SWAT_USER));
-			printf("\n");
+			printf("%s\n", _(" The passwd has NOT been changed."));
 		}
 	}
@@ -1139,12 +1247,6 @@
 {
 	const char *new_name = cgi_user_name();
-
-	/* 
-	 * After the first time through here be nice. If the user
-	 * changed the User box text to another users name, remember it.
-	 */
-	if (cgi_variable(SWAT_USER)) {
-		new_name = cgi_variable_nonull(SWAT_USER);
-	} 
+	const char passwd_form[] = "passwd";
+	const char rpasswd_form[] = "rpasswd";
 
 	if (!new_name) new_name = "";
@@ -1153,4 +1255,5 @@
 
 	printf("<FORM name=\"swatform\" method=post>\n");
+	print_xsrf_token(cgi_user_name(), cgi_user_pass(), passwd_form);
 
 	printf("<table>\n");
@@ -1192,6 +1295,7 @@
 	 * requested. It could be this is the first time through this
 	 * code, so there isn't anything to do.  */
-	if ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
-	    (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG))) {
+	if (verify_xsrf_token(passwd_form) &&
+	   ((cgi_variable(CHG_S_PASSWD_FLAG)) || (cgi_variable(ADD_USER_FLAG)) || (cgi_variable(DELETE_USER_FLAG)) ||
+	    (cgi_variable(DISABLE_USER_FLAG)) || (cgi_variable(ENABLE_USER_FLAG)))) {
 		chg_passwd();		
 	}
@@ -1200,4 +1304,5 @@
 
 	printf("<FORM name=\"swatform\" method=post>\n");
+	print_xsrf_token(cgi_user_name(), cgi_user_pass(), rpasswd_form);
 
 	printf("<table>\n");
@@ -1232,5 +1337,5 @@
 	 * is the first time through this code, so there isn't
 	 * anything to do.  */
-	if (cgi_variable(CHG_R_PASSWD_FLAG)) {
+	if (verify_xsrf_token(passwd_form) && cgi_variable(CHG_R_PASSWD_FLAG)) {
 		chg_passwd();		
 	}
@@ -1249,15 +1354,12 @@
 	int mode = 0;
 	unsigned int parm_filter = FLAG_BASIC;
+	const char form_name[] = "printers";
+
+	if (!verify_xsrf_token(form_name)) {
+		goto output_page;
+	}
 
 	if (share)
 		snum = lp_servicenumber(share);
-
-        printf("<H2>%s</H2>\n", _("Printer Parameters"));
- 
-        printf("<H3>%s</H3>\n", _("Important Note:"));
-        printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
-        printf("%s",_("are autoloaded printers from "));
-        printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
-        printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
 
 	if (cgi_variable("Commit") && snum >= 0) {
@@ -1289,6 +1391,4 @@
 	}
 
-	printf("<FORM name=\"swatform\" method=post>\n");
-
 	if ( cgi_variable("ViewMode") )
 		mode = atoi(cgi_variable_nonull("ViewMode"));
@@ -1297,4 +1397,17 @@
         if ( cgi_variable("AdvMode"))
                 mode = 1;
+
+output_page:
+        printf("<H2>%s</H2>\n", _("Printer Parameters"));
+
+        printf("<H3>%s</H3>\n", _("Important Note:"));
+        printf("%s",_("Printer names marked with [*] in the Choose Printer drop-down box "));
+        printf("%s",_("are autoloaded printers from "));
+        printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
+        printf("%s\n", _("Attempting to delete these printers from SWAT will have no effect."));
+
+
+	printf("<FORM name=\"swatform\" method=post>\n");
+	print_xsrf_token(cgi_user_name(), cgi_user_pass(), form_name);
 
 	ViewModeBoxes( mode );
Index: trunk/server/source3/web/swat_proto.h
===================================================================
--- trunk/server/source3/web/swat_proto.h	(revision 604)
+++ trunk/server/source3/web/swat_proto.h	(revision 617)
@@ -32,4 +32,5 @@
 bool am_root(void);
 char *cgi_user_name(void);
+char *cgi_user_pass(void);
 void cgi_setup(const char *rootdir, int auth_required);
 const char *cgi_baseurl(void);
@@ -67,4 +68,9 @@
 
 const char *lang_msg_rotate(TALLOC_CTX *ctx, const char *msgid);
+void get_xsrf_token(const char *username, const char *pass,
+		    const char *formname, time_t xsrf_time, char token_str[33]);
+void print_xsrf_token(const char *username, const char *pass,
+		      const char *formname);
+bool verify_xsrf_token(const char *formname);
 
 #endif /*  _SWAT_PROTO_H_  */
