diff --git a/source3/include/proto.h b/source3/include/proto.h index 5c0efaf93c0..24d4040c3ce 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2657,4 +2657,5 @@ void status_page(void); /*The following definitions come from web/swat.c */ +BOOL become_user_permanently(uid_t uid, gid_t gid); #endif /* _PROTO_H_ */ diff --git a/source3/web/cgi.c b/source3/web/cgi.c index 5415abf6b3e..9b5cf2158cc 100644 --- a/source3/web/cgi.c +++ b/source3/web/cgi.c @@ -293,29 +293,83 @@ static void base64_decode(char *s) /*************************************************************************** handle a http authentication line ***************************************************************************/ -static int cgi_handle_authorization(char *line) +static BOOL cgi_handle_authorization(char *line) { - char *p, *user, *pass; + char *p, *user, *user_pass; + struct passwd *pass = NULL; + int ret = False; if (strncasecmp(line,"Basic ", 6)) { cgi_setup_error("401 Bad Authorization", "", "Only basic authorization is understood"); + return False; } line += 6; while (line[0] == ' ') line++; base64_decode(line); if (!(p=strchr(line,':'))) { + /* + * Always give the same error so a cracker + * cannot tell why we fail. + */ cgi_setup_error("401 Bad Authorization", "", "username/password must be supplied"); + return False; } *p = 0; user = line; - pass = p+1; + user_pass = p+1; - /* Save the users name */ - C_user = strdup(user); + /* + * Try and get the user from the UNIX password file. + */ - return pass_check(user, pass, strlen(pass), NULL, NULL); + if(!(pass = Get_Pwnam(user,False))) { + /* + * Always give the same error so a cracker + * cannot tell why we fail. + */ + cgi_setup_error("401 Bad Authorization", "", + "username/password must be supplied"); + return False; + } + + /* + * Validate the password they have given. + */ + + if((ret = pass_check(user, user_pass, strlen(user_pass), NULL, NULL)) == True) { + + /* + * Password was ok. + */ + + if(pass->pw_uid != 0) { + /* + * We have not authenticated as root, + * become the user *permanently*. + */ + if(!become_user_permanently(pass->pw_uid, pass->pw_gid)) { + /* + * Always give the same error so a cracker + * cannot tell why we fail. + */ + cgi_setup_error("401 Bad Authorization", "", + "username/password must be supplied"); + return False; + } + + /* + * On exit from here we are the authenticated + * user - no way back. + */ + } + + /* Save the users name */ + C_user = strdup(user); + } + + return ret; } /*************************************************************************** @@ -323,7 +377,7 @@ is this root? ***************************************************************************/ BOOL am_root(void) { - if ((C_user) && (strcmp(C_user,"root") == 0)) { + if (geteuid() == 0) { return( True); } else { return( False); @@ -393,7 +447,7 @@ run as a true cgi program by a web browser or is itself a mini web server ***************************************************************************/ void cgi_setup(char *rootdir, int auth_required) { - int authenticated = 0; + BOOL authenticated = False; char line[1024]; char *url=NULL; char *p; diff --git a/source3/web/swat.c b/source3/web/swat.c index 1030689f18d..1ab90a3a3dd 100644 --- a/source3/web/swat.c +++ b/source3/web/swat.c @@ -771,76 +771,64 @@ static BOOL talk_to_smbpasswd(char *old, char *new) } /**************************************************************************** - become the specified uid + become the specified uid - permanently ! ****************************************************************************/ -static BOOL become_uid(uid_t uid) + +BOOL become_user_permanently(uid_t uid, gid_t gid) { -#ifdef HAVE_TRAPDOOR_UID -#ifdef HAVE_SETUIDX - /* AIX3 has setuidx which is NOT a trapoor function (tridge) */ - if (setuidx(ID_EFFECTIVE, uid) != 0) { - if (seteuid(uid) != 0) { - printf("

Can't set uid %d (setuidx)\n", (int)uid); - return False; - } - } -#endif -#endif + + if (geteuid() != 0) { + return(True); + } + + /* now completely lose our privilages. This is a fairly paranoid + way of doing it, but it does work on all systems that I know of */ #ifdef HAVE_SETRESUID - if (setresuid(-1,uid,-1) != 0) + /* + * Firstly ensure all our uids are set to root. + */ + setresgid(0,0,0); + setresuid(0,0,0); + + /* + * Now ensure we change all our gids. + */ + setresgid(gid,gid,gid); + + /* + * Now ensure all the uids are the user. + */ + setresuid(uid,uid,uid); #else - if ((seteuid(uid) != 0) && (setuid(uid) != 0)) + /* + * Firstly ensure all our uids are set to root. + */ + setuid(0); + seteuid(0); + + /* + * Now ensure we change all our gids. + */ + setgid(gid); + setegid(gid); + + /* + * Now ensure all the uids are the user. + */ + setuid(uid); + seteuid(uid); #endif - { - printf("

Couldn't set uid %d currently set to (uid %d, euid %d)\n", - (int)uid,(int)getuid(), (int)geteuid()); - if (uid > (uid_t)32000) { - printf("

Looks like your OS doesn't like high uid values - try using a different account\n"); - } - return(False); - } - - if (((uid == (uid_t)-1) || ((sizeof(uid_t) == 2) && (uid == 65535))) && - (geteuid() != uid)) { - printf("

Invalid uid -1. perhaps you have a account with uid 65535?\n"); - return(False); - } + if (getuid() != uid || geteuid() != uid || + getgid() != gid || getegid() != gid) { + /* We failed to lose our privilages. */ + return False; + } return(True); } -/**************************************************************************** - become the specified gid -****************************************************************************/ -static BOOL become_gid(gid_t gid) -{ -#ifdef HAVE_SETRESUID - if (setresgid(-1,gid,-1) != 0) -#else - if (setgid(gid) != 0) -#endif - { - printf("

Couldn't set gid %d currently set to (gid %d, egid %d)\n", - (int)gid,(int)getgid(),(int)getegid()); - if (gid > 32000) { - printf("

Looks like your OS doesn't like high gid values - try using a different account\n"); - } - return(False); - } - - return(True); -} - -/**************************************************************************** - become the specified uid and gid -****************************************************************************/ -static BOOL become_id(uid_t uid,gid_t gid) -{ - return(become_gid(gid) && become_uid(uid)); -} - /**************************************************************************** do the stuff required to add or change a password ****************************************************************************/ @@ -881,19 +869,6 @@ static void chg_passwd(void) } } - /* Get the UID/GID of the user, and become that user */ - if (am_root() == False) { - pass = Get_Pwnam(cgi_variable(user),True); - if (pass == NULL) { - printf("

User uid unknown \n"); - } else { - if (become_id(pass->pw_uid, pass->pw_gid) == False) { - printf("

uid/gid set failed \n"); - return; - } - } - } - #ifdef SWAT_DEBUG if (pass) printf("

User uid %d gid %d \n", pass->pw_uid, pass->pw_gid); printf("

Processes uid %d, euid %d, gid %d, egid %d \n",getuid(),geteuid(),getgid(),getegid()); @@ -1138,4 +1113,3 @@ static void printers_page(void) print_footer(); return 0; } -