fix security system to actually work now

This commit is contained in:
Matt Wells
2014-02-12 00:06:00 -07:00
parent 609a344a57
commit 3b0a571cea
12 changed files with 143 additions and 74 deletions

@ -604,7 +604,7 @@ bool Collectiondb::addRdbBasesForCollRec ( CollectionRec *cr ) {
/*
bool Collectiondb::isAdmin ( HttpRequest *r , TcpSocket *s ) {
if ( r->getLong("admin",1) == 0 ) return false;
if ( g_conf.isMasterAdmin ( s , r ) ) return true;
@ -615,7 +615,6 @@ bool Collectiondb::isAdmin ( HttpRequest *r , TcpSocket *s ) {
//return cr->hasPermission ( r , s );
}
/*
void savingCheckWrapper1 ( int fd , void *state ) {
WaitEntry *we = (WaitEntry *)state;
// no state?

@ -95,7 +95,7 @@ class Collectiondb {
// . does this requester have root admin privledges???
// . uses the root collection record!
bool isAdmin ( class HttpRequest *r , class TcpSocket *s );
//bool isAdmin ( class HttpRequest *r , class TcpSocket *s );
//collnum_t getNextCollnum ( collnum_t collnum );
@ -310,10 +310,10 @@ class CollectionRec {
// . set ourselves the cgi parms in an http request
// . unspecified cgi parms will be assigned default values
// . returns false and sets errno on error
bool set ( class HttpRequest *r , TcpSocket *s );
bool set ( class HttpRequest *r , class TcpSocket *s );
// calls hasPermission() below
bool hasPermission ( class HttpRequest *r , TcpSocket *s ) ;
bool hasPermission ( class HttpRequest *r , class TcpSocket *s ) ;
// . does this user have permission for editing this collection?
// . "p" is the password for this collection in question
@ -326,7 +326,7 @@ class CollectionRec {
// . can this ip perform a search or add url on this collection?
// . mamma.com provides encapsulated ips of their queriers so we
// can ban them by ip
bool hasSearchPermission ( TcpSocket *s , long encapIp = 0 );
bool hasSearchPermission ( class TcpSocket *s , long encapIp = 0 );
// how many bytes would this record occupy in raw binary format?
//long getStoredSize () { return m_recSize; };

@ -18,6 +18,7 @@ Conf::Conf ( ) {
// . master admin can administer ALL collections
// . use CollectionRec::hasPermission() to see if has permission
// to adminster one particular collection
/*
bool Conf::isMasterAdmin ( TcpSocket *s , HttpRequest *r ) {
// sometimes they don't want to be admin intentionally for testing
if ( r->getLong ( "master" , 1 ) == 0 ) return false;
@ -64,56 +65,84 @@ bool Conf::isMasterAdmin ( TcpSocket *s , HttpRequest *r ) {
// check admin ips
// scan the passwords
// MDW: no! too vulnerable to attacks!
/*
for ( long i = 0 ; i < m_numMasterPwds ; i++ ) {
if ( strcmp ( m_masterPwds[i], p ) != 0 ) continue;
// . matching one password is good enough now, default OR
// . because just matching an IP is good enough security,
// there is really no need for both IP AND passwd match
return true;
}
*/
//for ( long i = 0 ; i < m_numMasterPwds ; i++ ) {
// if ( strcmp ( m_masterPwds[i], p ) != 0 ) continue;
// // . matching one password is good enough now, default OR
// // . because just matching an IP is good enough security,
// // there is really no need for both IP AND passwd match
// return true;
//}
// ok, make sure they came from an acceptable IP
if ( isAdminIp ( ip ) )
if ( isRootIp ( ip ) )
// they also have a matching IP, so they now have permission
return true;
// if no security, allow all
// MDW: nonononono!!!!
/*
if ( m_numMasterPwds == 0 &&
m_numMasterIps == 0 ) return true;
*/
//if ( m_numMasterPwds == 0 &&
// m_numMasterIps == 0 ) return true;
// if they did not match an ip or password, even if both lists
// are empty, do not allow access... this prevents security breeches
// by accident
return false;
}
*/
bool Conf::isCollAdmin ( TcpSocket *socket , HttpRequest *hr ) {
// until we have coll tokens use this...
return isRootAdmin ( socket , hr );
}
// is user a root administrator?
// . is user a root administrator?
// . only need to be from root IP *OR* have password, not both
bool Conf::isRootAdmin ( TcpSocket *socket , HttpRequest *hr ) {
if ( m_numMasterIps == 0 &&
m_numConnectIps == 0 ) {
// from "local" ip?
return hr->isLocal();
}
// totally open access?
if ( m_numConnectIps <= 0 && m_numMasterPwds <= 0 )
return true;
if ( isAdminIp ( socket->m_ip ) ) return true;
// coming from root gets you in
if ( isRootIp ( socket->m_ip ) ) return true;
if ( isConnectIp ( socket->m_ip ) ) return true;
//if ( isConnectIp ( socket->m_ip ) ) return true;
if ( hasRootPwd ( hr ) ) return true;
return false;
}
bool Conf::hasRootPwd ( HttpRequest *hr ) {
if ( m_numMasterPwds == 0 ) return false;
char *p = hr->getString("pwd");
if ( ! p ) p = hr->getString("password");
if ( ! p ) p = hr->getStringFromCookie("pwd");
if ( ! p ) return false;
for ( long i = 0 ; i < m_numMasterPwds ; i++ ) {
if ( strcmp ( m_masterPwds[i], p ) != 0 ) continue;
// we got a match
return true;
}
return false;
}
// . check this ip in the list of admin ips
bool Conf::isAdminIp ( unsigned long ip ) {
for ( long i = 0 ; i < m_numMasterIps ; i++ )
if ( m_masterIps[i] == (long)ip )
bool Conf::isRootIp ( unsigned long ip ) {
//if ( m_numMasterIps == 0 ) return false;
if ( m_numConnectIps == 0 ) return false;
for ( long i = 0 ; i < m_numConnectIps ; i++ )
if ( m_connectIps[i] == (long)ip )
return true;
//if ( ip == atoip("10.5.0.2",8) ) return true;
// no match
return false;
}

14
Conf.h

@ -49,10 +49,13 @@ class Conf {
Conf();
bool isCollAdmin ( TcpSocket *socket , HttpRequest *hr ) ;
bool isRootAdmin ( TcpSocket *socket , HttpRequest *hr ) ;
bool isMasterAdmin ( class TcpSocket *s , class HttpRequest *r );
bool isSpamAssassin ( class TcpSocket *s , class HttpRequest *r );
bool isAdminIp ( unsigned long ip );
//bool isMasterAdmin ( class TcpSocket *s , class HttpRequest *r );
//bool isSpamAssassin ( class TcpSocket *s , class HttpRequest *r );
bool hasRootPwd ( HttpRequest *hr ) ;
bool isRootIp ( unsigned long ip );
bool isConnectIp ( unsigned long ip );
// loads conf parms from this file "{dir}/gb.conf"
@ -664,9 +667,10 @@ class Conf {
long m_numMasterPwds;
char m_masterPwds[MAX_MASTER_PASSWORDS][PASSWORD_MAX_LEN];
long m_numMasterIps;
long m_masterIps[MAX_MASTER_IPS];
//long m_numMasterIps;
//long m_masterIps[MAX_MASTER_IPS];
// these are the new master ips
long m_numConnectIps;
long m_connectIps [ MAX_CONNECT_IPS ];

@ -120,7 +120,7 @@ bool sendPageGet ( TcpSocket *s , HttpRequest *r ) {
mnew ( st , sizeof(State2) , "PageGet1" );
// save the socket and if Host: is local in the Http request Mime
st->m_socket = s;
st->m_isAdmin = g_collectiondb.isAdmin ( r , s );
st->m_isAdmin = g_conf.isCollAdmin ( s , r );
st->m_isLocal = r->isLocal();
st->m_docId = docId;
// include header ... "this page cached by Gigablast on..."

@ -124,7 +124,7 @@ bool sendPageIndexdb ( TcpSocket *s , HttpRequest *r ) {
// save the TcpSocket
st->m_socket = s;
// and if the request is local/internal or not
st->m_isAdmin = g_collectiondb.isAdmin ( r , s );
st->m_isAdmin = g_conf.isCollAdmin ( s , r );
st->m_isLocal = r->isLocal();
st->m_r.copy ( r );
// . check for add/delete request

@ -1286,7 +1286,7 @@ bool sendPageAddUrl ( TcpSocket *s , HttpRequest *r ) {
// see if they provided a url of a file of urls if they did not
// provide a url to add directly
bool isAdmin = g_collectiondb.isAdmin ( r , s );
bool isAdmin = g_conf.isCollAdmin ( s , r );
long ufuLen = 0;
char *ufu = NULL;
if ( isAdmin )

@ -58,7 +58,7 @@ bool sendPageTitledb ( TcpSocket *s , HttpRequest *r ) {
// copy it
st->m_r.copy ( r );
// remember if http request is internal/local or not
st->m_isAdmin = g_collectiondb.isAdmin ( r , s );
st->m_isAdmin = g_conf.isCollAdmin ( s , r );
st->m_isLocal = r->isLocal();
st->m_docId = docId;
// password, too

@ -1005,6 +1005,25 @@ bool Pages::printAdminTop (SafeBuf *sb ,
//
sb->safePrintf("</TD>\n<TD>");
// logout link on far right
sb->safePrintf("<div align=right "
"style=\""
"max-width:100px;"
"right:20px;"
"position:absolute;"
"\">"
"<font color=blue>"
// clear the cookie
"<span onclick=\"document.cookie='pwd=;';"
"window.location.href='/';"
"\">"
"logout"
"</span>"
"</font>"
"</div>"
);
// print the hosts navigation bar
status &= printHostLinks ( sb, page ,
username , pwd ,
@ -2503,7 +2522,7 @@ bool sendPageLogin ( TcpSocket *socket , HttpRequest *hr ) {
emsg.safePrintf("Collection \"%s\" does not exist.",coll);
// just make cookie same format as an http request for ez parsing
char cookieData[2024];
//char cookieData[2024];
SafeBuf sb;
@ -2515,7 +2534,10 @@ bool sendPageLogin ( TcpSocket *socket , HttpRequest *hr ) {
g_pages.printLogo ( &sb , coll );
// get password from cgi parms OR cookie
char *pwd = hr->getString("pwd",NULL);
char *pwd = hr->getString("pwd");
if ( ! pwd ) pwd = hr->getStringFromCookie("pwd");
// fix "pwd=" cookie (from logout) issue
if ( pwd && ! pwd[0] ) pwd = NULL;
bool hasPermission = false;
@ -2523,8 +2545,9 @@ bool sendPageLogin ( TcpSocket *socket , HttpRequest *hr ) {
if ( cr && pwd && g_conf.isRootAdmin ( socket , hr ) )
hasPermission = true;
if ( emsg.length() == 0 && ! hasPermission )
emsg.safePrintf("Admin password incorrect");
if ( emsg.length() == 0 && ! hasPermission && pwd )
emsg.safePrintf("Root password incorrect");
// sanity
if ( hasPermission && emsg.length() ) { char *xx=NULL;*xx=0; }
@ -2532,42 +2555,52 @@ bool sendPageLogin ( TcpSocket *socket , HttpRequest *hr ) {
// what page are they originally trying to get to?
long page = g_pages.getDynamicPageNumber(hr);
char *cookie = NULL;
// try to the get reference Page
long refPage = hr->getLong("ref",-1);
// if they cam to login page directly... to to basic page then
if ( refPage == PAGE_LOGIN ||
refPage == PAGE_LOGIN2 ||
refPage < 0 )
refPage = PAGE_BASIC_SETTINGS;
// if they had an original destination, redirect there NOW
WebPage *pagePtr = g_pages.getPage(refPage);
/*
char *cookie = NULL;
if ( hasPermission ) {
// "pwd" could be NULL... like when it is not required,
// perhaps only the right ip address is required, but if it
// is there then store it in a cookie with no expiration
if ( pwd ) sprintf ( cookieData, "pwd=%s;expires=0;",pwd);
// try to the get reference Page
long refPage = hr->getLong("ref",-1);
// if they cam to login page directly... to to basic page then
if ( refPage == PAGE_LOGIN ||
refPage == PAGE_LOGIN2 ||
refPage < 0 )
refPage = PAGE_BASIC_SETTINGS;
// if they had an original destination, redirect there NOW
WebPage *page = g_pages.getPage(refPage);
//if ( pwd ) sprintf ( cookieData, "pwd=%s;expires=0;",pwd);
// and redirect to it
sb.safePrintf("<meta http-equiv=\"refresh\" content=\"0;"
"/%s?c=%s\">", page->m_filename,coll);
// return cookie in server reply if pwd was non-null
cookie = cookieData;
}
*/
char *ep = emsg.getBufStart();
if ( !ep ) ep = "";
char *ff = "admin/settings";
if ( pagePtr ) ff = pagePtr->m_filename;
sb.safePrintf(
"&nbsp; &nbsp; "
"</td><td><font size=+1><b>Login</b></font></td></tr>"
"</table>"
"<form method=post action=\"/login\" name=f>"
"&nbsp; &nbsp; "
"</td><td><font size=+1><b>Login</b></font></td></tr>"
"</table>"
"<form method=post action=\"/%s\" name=f>"
, ff );
sb.safePrintf(
"<input type=hidden name=ref value=\"%li\">"
"<center>"
"<br><br>"
"<font color=ff0000><b>%s</b></font>"
"<br><br>"
"<br>"
"<table cellpadding=2><tr><td>"
@ -2576,17 +2609,21 @@ bool sendPageLogin ( TcpSocket *socket , HttpRequest *hr ) {
//"</td><td></td></tr>"
//"<tr><td>"
"<b>Admin Password</td>"
"<td><input type=password name=pwd size=30>"
"<b>Root Password : &nbsp; </td>"
"<td><input id=ppp type=password name=pwd size=30>"
"</td><td>"
"<input type=submit value=ok border=0></td>"
"<input type=submit value=ok border=0 onclick=\""
"document.cookie='pwd='+document.getElementById('ppp')"
".value+"
"';expires=0';"
"\"></td>"
"</tr></table>"
"</center>"
"<br><br>"
, page, ep , coll );
// print the tail
g_pages.printTail ( &sb , hr->isLocal() ); // pwd
//g_pages.printTail ( &sb , hr->isLocal() ); // pwd
// send the page
return g_httpServer.sendDynamicPage ( socket ,
sb.getBufStart(),
@ -2595,5 +2632,5 @@ bool sendPageLogin ( TcpSocket *socket , HttpRequest *hr ) {
false , // POSTReply?
NULL , // contentType
-1 ,
cookie);// Forbidden http status
NULL);// cookie
}

@ -8015,13 +8015,13 @@ void Parms::init ( ) {
m->m_title = "Admin Passwords";
m->m_desc = "Passwords allowed to change Gigablast's general "
"parameters and also the parameters for any collection. "
"If no Admin Password or Admin IP is specified then "
"Gigablast will only allow local IPs to connect to it "
"as the master admin.";
m->m_cgi = "mpwd";
m->m_xml = "masterPassword";
m->m_desc = "Any matching password will have administrative access "
"to Gigablast and all collections.";
//"If no Admin Password or Admin IP is specified then "
//"Gigablast will only allow local IPs to connect to it "
//"as the master admin.";
m->m_cgi = "adminpwd";
m->m_xml = "adminPassword";
m->m_obj = OBJ_CONF;
m->m_max = MAX_MASTER_PASSWORDS;
m->m_off = (char *)&g_conf.m_masterPwds - g;
@ -8042,7 +8042,7 @@ void Parms::init ( ) {
// "their Least Significant Byte are treated as wildcards for "
// "IP blocks. That is, 1.2.3.0 means 1.2.3.*.";
m->m_desc = "Any IPs in this list will have administrative access "
"to the Gigablast search engine.";
"to Gigablast and all collections.";
m->m_cgi = "adminip";
m->m_xml = "adminIp";
m->m_page = PAGE_SECURITY;

@ -339,7 +339,7 @@ bool Proxy::handleRequest (TcpSocket *s){
return false;
}
bool isAdmin = g_conf.isMasterAdmin(s,&hr);
bool isAdmin = g_conf.isRootAdmin(s,&hr);
long redirLen = hr.getRedirLen() ;
char *redir = NULL;

@ -1237,7 +1237,7 @@ long UdpServer::readSock_ass ( UdpSlot **slotPtr , long long now ) {
else if ( m_proto->useAcks() &&
! isLocal &&
! g_hostdb.isIpInNetwork ( ip ) &&
! g_conf.isAdminIp ( ip ) &&
! g_conf.isRootIp ( ip ) &&
! g_hostdb2.isIpInNetwork ( ip ) &&
! g_conf.isConnectIp ( ip ) ) {
// bitch, wait at least 5 seconds though