diff options
-rw-r--r-- | WHATSNEW.txt | 62 | ||||
-rw-r--r-- | packaging/RHEL-CTDB/samba.spec | 2 | ||||
-rw-r--r-- | packaging/RHEL/makerpms.sh | 2 | ||||
-rw-r--r-- | packaging/RHEL/samba.spec | 2 | ||||
-rw-r--r-- | source3/VERSION | 2 | ||||
-rw-r--r-- | source3/include/version.h | 4 | ||||
-rw-r--r-- | source3/web/cgi.c | 29 | ||||
-rw-r--r-- | source3/web/statuspage.c | 7 | ||||
-rw-r--r-- | source3/web/swat.c | 175 | ||||
-rw-r--r-- | source3/web/swat_proto.h | 6 |
10 files changed, 251 insertions, 40 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt index f9b4a46c28..2f75a9ae43 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,3 +1,61 @@ + ============================== + 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 June 14, 2011 @@ -142,8 +200,8 @@ database (https://bugzilla.samba.org/). ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- + ============================= Release Notes for Samba 3.5.8 diff --git a/packaging/RHEL-CTDB/samba.spec b/packaging/RHEL-CTDB/samba.spec index 08260fdcb0..efb7572b56 100644 --- a/packaging/RHEL-CTDB/samba.spec +++ b/packaging/RHEL-CTDB/samba.spec @@ -5,7 +5,7 @@ Summary: Samba SMB client and server Vendor: Samba Team Packager: Samba Team <samba@samba.org> Name: samba -Version: 3.5.9 +Version: 3.5.10 Release: 1GITHASH Epoch: 0 License: GNU GPL version 3 diff --git a/packaging/RHEL/makerpms.sh b/packaging/RHEL/makerpms.sh index 8e88629889..cb72f5205b 100644 --- a/packaging/RHEL/makerpms.sh +++ b/packaging/RHEL/makerpms.sh @@ -20,7 +20,7 @@ SRCDIR=`rpm --eval %_sourcedir` USERID=`id -u` GRPID=`id -g` -VERSION='3.5.9' +VERSION='3.5.10' REVISION='' SPECFILE="samba.spec" RPMVER=`rpm --version | awk '{print $3}'` diff --git a/packaging/RHEL/samba.spec b/packaging/RHEL/samba.spec index 84ce96b2ba..3c70de6810 100644 --- a/packaging/RHEL/samba.spec +++ b/packaging/RHEL/samba.spec @@ -5,7 +5,7 @@ Summary: Samba SMB client and server Vendor: Samba Team Packager: Samba Team <samba@samba.org> Name: samba -Version: 3.5.9 +Version: 3.5.10 Release: 1 Epoch: 0 License: GNU GPL version 3 diff --git a/source3/VERSION b/source3/VERSION index e79324d567..b6c1cd139d 100644 --- a/source3/VERSION +++ b/source3/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=3 SAMBA_VERSION_MINOR=5 -SAMBA_VERSION_RELEASE=9 +SAMBA_VERSION_RELEASE=10 ######################################################## # Bug fix releases use a letter for the patch revision # diff --git a/source3/include/version.h b/source3/include/version.h index d6c53fe846..e1296ee0c2 100644 --- a/source3/include/version.h +++ b/source3/include/version.h @@ -1,8 +1,8 @@ /* Autogenerated by script/mkversion.sh */ #define SAMBA_VERSION_MAJOR 3 #define SAMBA_VERSION_MINOR 5 -#define SAMBA_VERSION_RELEASE 9 -#define SAMBA_VERSION_OFFICIAL_STRING "3.5.9" +#define SAMBA_VERSION_RELEASE 10 +#define SAMBA_VERSION_OFFICIAL_STRING "3.5.10" #ifdef SAMBA_VERSION_VENDOR_FUNCTION # define SAMBA_VERSION_STRING SAMBA_VERSION_VENDOR_FUNCTION #else /* SAMBA_VERSION_VENDOR_FUNCTION */ diff --git a/source3/web/cgi.c b/source3/web/cgi.c index cf91b02175..0c8e9cbe55 100644 --- a/source3/web/cgi.c +++ b/source3/web/cgi.c @@ -19,6 +19,8 @@ #include "includes.h" #include "web/swat_proto.h" +#include "secrets.h" +#include "../lib/util/util.h" #define MAX_VARIABLES 10000 @@ -42,6 +44,7 @@ static char *query_string; static const char *baseurl; static char *pathinfo; static char *C_user; +static char *C_pass; static bool inetd_server; static bool got_request; @@ -320,7 +323,23 @@ static void cgi_web_auth(void) exit(0); } - 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) { printf("%sFailed to become user %s - uid=%d/%d<br>%s\n", @@ -388,6 +407,7 @@ static bool cgi_handle_authorization(char *line) /* Save the users name */ C_user = SMB_STRDUP(user); + C_pass = SMB_STRDUP(user_pass); TALLOC_FREE(pass); return True; } @@ -422,6 +442,13 @@ char *cgi_user_name(void) return(C_user); } +/*************************************************************************** +return a ptr to the users password + ***************************************************************************/ +char *cgi_user_pass(void) +{ + return(C_pass); +} /*************************************************************************** handle a file download diff --git a/source3/web/statuspage.c b/source3/web/statuspage.c index 590be1dde2..cb5c57b6ee 100644 --- a/source3/web/statuspage.c +++ b/source3/web/statuspage.c @@ -247,9 +247,14 @@ void status_page(void) int nr_running=0; 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")) { stop_smbd(); start_smbd(); @@ -326,9 +331,11 @@ void status_page(void) 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) { printf("<input type=submit value=\"%s\" name=\"autorefresh\">\n", _("Auto Refresh")); diff --git a/source3/web/swat.c b/source3/web/swat.c index baffa44bae..3a88986f38 100644 --- a/source3/web/swat.c +++ b/source3/web/swat.c @@ -29,6 +29,7 @@ #include "includes.h" #include "web/swat_proto.h" +#include "../lib/crypto/md5.h" static int demo_mode = False; static int passwd_only = False; @@ -50,6 +51,9 @@ static int iNumNonAutoPrintServices = 0; #define DISABLE_USER_FLAG "disable_user_flag" #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,6 +142,76 @@ static char *make_parm_name(const char *label) 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); +} + + /**************************************************************************** include a lump of html in a page ****************************************************************************/ @@ -611,13 +685,20 @@ static void welcome_page(void) static void viewconfig_page(void) { int full_view=0; + const char form_name[] = "viewconfig"; + + if (!verify_xsrf_token(form_name)) { + goto output_page; + } if (cgi_variable("full_view")) { full_view = 1; } +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) { printf("<input type=submit name=\"normal_view\" value=\"%s\">\n", _("Normal View")); @@ -637,18 +718,25 @@ static void viewconfig_page(void) static void wizard_params_page(void) { unsigned int parm_filter = FLAG_WIZARD; + const char form_name[] = "wizard_params"; /* Here we first set and commit all the parameters that were selected in the previous screen. */ printf("<H2>%s</H2>\n", _("Wizard Parameter Edit Page")); + if (!verify_xsrf_token(form_name)) { + goto output_page; + } + if (cgi_variable("Commit")) { commit_parameters(GLOBAL_SECTION_SNUM); save_reload(-1); } +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) { printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n"); @@ -684,6 +772,11 @@ static void wizard_page(void) int have_home = -1; int HomeExpo = 0; int SerType = 0; + const char form_name[] = "wizard"; + + if (!verify_xsrf_token(form_name)) { + goto output_page; + } if (cgi_variable("Rewrite")) { (void) rewritecfg_file(); @@ -774,10 +867,12 @@ static void wizard_page(void) winstype = 3; 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) { printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments.")); @@ -846,9 +941,14 @@ static void globals_page(void) { 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")) { commit_parameters(GLOBAL_SECTION_SNUM); save_reload(-1); @@ -861,7 +961,9 @@ static void globals_page(void) if ( cgi_variable("AdvMode")) 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 ); switch ( mode ) { @@ -901,11 +1003,17 @@ static void shares_page(void) int mode = 0; 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) { commit_parameters(snum); @@ -931,10 +1039,6 @@ static void shares_page(void) } } - printf("<FORM name=\"swatform\" method=post>\n"); - - printf("<table>\n"); - if ( cgi_variable("ViewMode") ) mode = atoi(cgi_variable_nonull("ViewMode")); if ( cgi_variable("BasicMode")) @@ -942,6 +1046,12 @@ static void shares_page(void) 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 ); switch ( mode ) { case 0: @@ -1121,11 +1231,9 @@ static void chg_passwd(void) if(cgi_variable(CHG_S_PASSWD_FLAG)) { 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.")); } } @@ -1138,20 +1246,15 @@ static void chg_passwd(void) static void passwd_page(void) { 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 = ""; printf("<H2>%s</H2>\n", _("Server Password Management")); printf("<FORM name=\"swatform\" method=post>\n"); + print_xsrf_token(cgi_user_name(), cgi_user_pass(), passwd_form); printf("<table>\n"); @@ -1191,14 +1294,16 @@ static void passwd_page(void) * Do some work if change, add, disable or enable was * 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(); } printf("<H2>%s</H2>\n", _("Client/Server Password Management")); printf("<FORM name=\"swatform\" method=post>\n"); + print_xsrf_token(cgi_user_name(), cgi_user_pass(), rpasswd_form); printf("<table>\n"); @@ -1231,7 +1336,7 @@ static void passwd_page(void) * password somewhere other than the server. It could be this * 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(); } @@ -1248,18 +1353,15 @@ static void printers_page(void) int i; 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) { commit_parameters(snum); if (snum >= iNumNonAutoPrintServices) @@ -1288,8 +1390,6 @@ static void printers_page(void) } } - printf("<FORM name=\"swatform\" method=post>\n"); - if ( cgi_variable("ViewMode") ) mode = atoi(cgi_variable_nonull("ViewMode")); if ( cgi_variable("BasicMode")) @@ -1297,6 +1397,19 @@ static void printers_page(void) 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 ); switch ( mode ) { case 0: diff --git a/source3/web/swat_proto.h b/source3/web/swat_proto.h index 0f84e4f4ce..424a3af545 100644 --- a/source3/web/swat_proto.h +++ b/source3/web/swat_proto.h @@ -31,6 +31,7 @@ const char *cgi_variable(const char *name); const char *cgi_variable_nonull(const char *name); 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); const char *cgi_pathinfo(void); @@ -66,5 +67,10 @@ void status_page(void); /* The following definitions come from web/swat.c */ 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_ */ |