2013-08-02 13:12:24 -07:00
|
|
|
#include "gb-include.h"
|
|
|
|
|
|
|
|
#include "Conf.h"
|
|
|
|
#include "Parms.h"
|
|
|
|
#include "Proxy.h"
|
2016-03-03 21:57:28 +01:00
|
|
|
#include "Msg3a.h" // MAX_SHARDS
|
2016-08-10 00:10:11 +02:00
|
|
|
#include "TcpSocket.h"
|
|
|
|
#include "HttpRequest.h"
|
2016-06-20 12:30:26 +02:00
|
|
|
#include "Process.h"
|
2016-08-10 00:32:00 +02:00
|
|
|
#include <sys/stat.h> //umask()
|
2016-06-20 12:30:26 +02:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
|
|
|
|
Conf g_conf;
|
|
|
|
|
2015-12-18 01:09:47 +01:00
|
|
|
static bool s_setUmask = false;
|
2015-09-22 12:23:33 -06:00
|
|
|
|
2015-09-21 12:44:41 -06:00
|
|
|
mode_t getFileCreationFlags() {
|
2015-09-22 12:23:33 -06:00
|
|
|
if ( ! s_setUmask ) {
|
|
|
|
s_setUmask = true;
|
|
|
|
umask ( 0 );
|
|
|
|
}
|
2016-04-29 14:29:06 +02:00
|
|
|
|
2015-09-22 12:23:33 -06:00
|
|
|
return S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH ;
|
2015-09-21 12:44:41 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
mode_t getDirCreationFlags() {
|
2015-09-22 12:23:33 -06:00
|
|
|
if ( ! s_setUmask ) {
|
|
|
|
s_setUmask = true;
|
|
|
|
umask ( 0 );
|
|
|
|
}
|
2016-04-29 14:29:06 +02:00
|
|
|
|
|
|
|
return S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IXUSR | S_IXGRP;
|
2015-09-21 12:44:41 -06:00
|
|
|
}
|
2015-09-21 11:19:34 -06:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
Conf::Conf ( ) {
|
|
|
|
m_save = true;
|
2014-04-22 11:18:21 -07:00
|
|
|
m_doingCommandLine = false;
|
2016-04-29 14:29:06 +02:00
|
|
|
|
2015-08-14 12:58:54 -06:00
|
|
|
// set max mem to 16GB at least until we load on disk
|
|
|
|
m_maxMem = 16000000000;
|
2013-08-02 13:12:24 -07:00
|
|
|
}
|
|
|
|
|
2016-02-25 17:38:31 +01:00
|
|
|
static bool isInWhiteSpaceList ( const char *p , const char *buf ) {
|
2014-09-29 18:28:36 -07:00
|
|
|
if ( ! p ) return false;
|
|
|
|
|
2016-02-25 17:38:31 +01:00
|
|
|
const char *match = strstr ( buf , p );
|
2014-09-29 18:28:36 -07:00
|
|
|
if ( ! match ) return false;
|
|
|
|
|
2016-07-28 17:04:35 +02:00
|
|
|
int32_t len = strlen(p);
|
2014-09-29 18:28:36 -07:00
|
|
|
|
|
|
|
// ensure book-ended by whitespace
|
|
|
|
if ( match &&
|
|
|
|
(match == buf || is_wspace_a(match[-1])) &&
|
|
|
|
(!match[len] || is_wspace_a(match[len])) )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// no match
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-09-30 15:40:02 -07:00
|
|
|
bool Conf::isCollAdmin ( TcpSocket *sock , HttpRequest *hr ) {
|
2014-11-13 13:04:28 -08:00
|
|
|
// master always does
|
|
|
|
if ( isMasterAdmin ( sock , hr ) ) return true;
|
2014-09-28 18:59:49 -07:00
|
|
|
|
|
|
|
CollectionRec *cr = g_collectiondb.getRec ( hr , true );
|
2014-09-29 18:28:36 -07:00
|
|
|
if ( ! cr ) return false;
|
2014-09-28 18:59:49 -07:00
|
|
|
|
2014-09-30 15:40:02 -07:00
|
|
|
return isCollAdmin2 ( sock , hr , cr );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-05-22 21:38:00 +02:00
|
|
|
bool Conf::isCollAdminForColl ( TcpSocket *sock, HttpRequest *hr, const char *coll ) {
|
2014-09-30 15:40:02 -07:00
|
|
|
CollectionRec *cr = g_collectiondb.getRec ( coll );
|
|
|
|
|
|
|
|
if ( ! cr ) return false;
|
|
|
|
|
|
|
|
return isCollAdmin2 ( sock , hr , cr );
|
|
|
|
}
|
|
|
|
|
2016-04-29 14:29:06 +02:00
|
|
|
bool Conf::isCollAdmin2 ( TcpSocket *sock, HttpRequest *hr, CollectionRec *cr ) {
|
2014-09-30 15:40:02 -07:00
|
|
|
if ( ! cr ) return false;
|
|
|
|
|
2015-12-11 19:07:14 +01:00
|
|
|
// never for main! must be root!
|
2014-09-29 18:28:36 -07:00
|
|
|
if ( strcmp(cr->m_coll,"main")==0 ) return false;
|
|
|
|
|
2015-03-02 07:47:05 -08:00
|
|
|
if ( ! g_conf.m_useCollectionPasswords) return false;
|
|
|
|
|
2014-09-29 18:28:36 -07:00
|
|
|
// empty password field? then allow them through
|
|
|
|
if ( cr->m_collectionPasswords.length() <= 0 &&
|
|
|
|
cr->m_collectionIps .length() <= 0 )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// a good ip?
|
2016-02-25 17:38:31 +01:00
|
|
|
const char *p = iptoa(sock->m_ip);
|
2014-09-29 18:28:36 -07:00
|
|
|
char *buf = cr->m_collectionIps.getBufStart();
|
|
|
|
if ( isInWhiteSpaceList ( p , buf ) ) return true;
|
|
|
|
|
|
|
|
// if they got the password, let them in
|
|
|
|
p = hr->getString("pwd");
|
|
|
|
if ( ! p ) p = hr->getString("password");
|
|
|
|
if ( ! p ) p = hr->getStringFromCookie("pwd");
|
|
|
|
if ( ! p ) return false;
|
|
|
|
buf = cr->m_collectionPasswords.getBufStart();
|
|
|
|
if ( isInWhiteSpaceList ( p , buf ) ) return true;
|
|
|
|
|
2014-09-28 18:59:49 -07:00
|
|
|
return false;
|
2014-02-12 00:06:00 -07:00
|
|
|
}
|
2014-09-28 18:59:49 -07:00
|
|
|
|
2014-02-08 16:24:33 -07:00
|
|
|
|
2014-02-12 00:06:00 -07:00
|
|
|
// . is user a root administrator?
|
|
|
|
// . only need to be from root IP *OR* have password, not both
|
2014-11-13 13:04:28 -08:00
|
|
|
bool Conf::isMasterAdmin ( TcpSocket *socket , HttpRequest *hr ) {
|
2015-02-12 11:16:34 -08:00
|
|
|
bool isAdmin = false;
|
|
|
|
|
2014-02-12 00:06:00 -07:00
|
|
|
// totally open access?
|
2014-09-28 18:59:49 -07:00
|
|
|
//if ( m_numConnectIps <= 0 && m_numMasterPwds <= 0 )
|
|
|
|
if ( m_connectIps.length() <= 0 &&
|
|
|
|
m_masterPwds.length() <= 0 )
|
2015-02-12 11:16:34 -08:00
|
|
|
isAdmin = true;
|
2014-02-08 16:24:33 -07:00
|
|
|
|
2014-02-12 00:06:00 -07:00
|
|
|
// coming from root gets you in
|
2015-02-12 17:00:38 -08:00
|
|
|
if ( socket && isMasterIp ( socket->m_ip ) )
|
2015-02-12 11:16:34 -08:00
|
|
|
isAdmin = true;
|
2014-02-08 16:24:33 -07:00
|
|
|
|
2015-02-12 11:16:34 -08:00
|
|
|
if ( hasMasterPwd ( hr ) )
|
|
|
|
isAdmin = true;
|
2014-02-08 16:24:33 -07:00
|
|
|
|
2015-02-12 11:16:34 -08:00
|
|
|
if ( ! isAdmin )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// default this to true so if user specifies &admin=0 then it
|
|
|
|
// cancels our admin view
|
|
|
|
if ( hr && ! hr->getLong("admin",1) )
|
|
|
|
return false;
|
2016-04-29 14:29:06 +02:00
|
|
|
|
2015-02-12 11:16:34 -08:00
|
|
|
return true;
|
2014-02-08 16:24:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-11-13 13:04:28 -08:00
|
|
|
bool Conf::hasMasterPwd ( HttpRequest *hr ) {
|
2014-09-28 18:59:49 -07:00
|
|
|
if ( m_masterPwds.length() <= 0 )
|
|
|
|
return false;
|
2014-02-12 00:06:00 -07:00
|
|
|
|
2016-02-25 17:38:31 +01:00
|
|
|
const char *p = hr->getString("pwd");
|
2014-02-12 00:06:00 -07:00
|
|
|
|
|
|
|
if ( ! p ) p = hr->getString("password");
|
|
|
|
|
|
|
|
if ( ! p ) p = hr->getStringFromCookie("pwd");
|
|
|
|
|
|
|
|
if ( ! p ) return false;
|
|
|
|
|
2016-02-25 17:38:31 +01:00
|
|
|
const char *buf = m_masterPwds.getBufStart();
|
2014-09-28 18:59:49 -07:00
|
|
|
|
2014-09-29 18:28:36 -07:00
|
|
|
return isInWhiteSpaceList ( p , buf );
|
2014-02-12 00:06:00 -07:00
|
|
|
}
|
2014-02-08 16:24:33 -07:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
// . check this ip in the list of admin ips
|
2014-11-20 16:53:07 -08:00
|
|
|
bool Conf::isMasterIp ( uint32_t ip ) {
|
2014-09-28 18:59:49 -07:00
|
|
|
if ( m_connectIps.length() <= 0 ) return false;
|
2014-02-12 00:06:00 -07:00
|
|
|
|
2014-09-28 18:59:49 -07:00
|
|
|
char *p = iptoa(ip);
|
|
|
|
char *buf = m_connectIps.getBufStart();
|
|
|
|
|
2014-09-29 18:28:36 -07:00
|
|
|
return isInWhiteSpaceList ( p , buf );
|
2013-08-02 13:12:24 -07:00
|
|
|
}
|
|
|
|
|
2014-11-10 14:45:11 -08:00
|
|
|
bool Conf::isConnectIp ( uint32_t ip ) {
|
2014-11-13 13:04:28 -08:00
|
|
|
return isMasterIp(ip);
|
2013-08-02 13:12:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// . set all member vars to their default values
|
|
|
|
void Conf::reset ( ) {
|
2014-06-18 05:04:45 -07:00
|
|
|
g_parms.setToDefault ( (char *)this , OBJ_CONF ,NULL);
|
2013-08-02 13:12:24 -07:00
|
|
|
m_save = true;
|
|
|
|
}
|
|
|
|
|
2014-11-10 14:45:11 -08:00
|
|
|
bool Conf::init ( char *dir ) { // , int32_t hostId ) {
|
2014-06-18 05:04:45 -07:00
|
|
|
g_parms.setToDefault ( (char *)this , OBJ_CONF ,NULL);
|
2013-08-02 13:12:24 -07:00
|
|
|
m_save = true;
|
2016-04-29 14:29:06 +02:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
char fname[1024];
|
2014-03-07 09:05:14 -08:00
|
|
|
File f;
|
2016-04-29 14:29:06 +02:00
|
|
|
|
2014-10-06 21:35:54 -07:00
|
|
|
m_isLocal = false;
|
2016-04-29 14:29:06 +02:00
|
|
|
|
2014-10-06 21:35:54 -07:00
|
|
|
if ( dir ) sprintf ( fname , "%sgb.conf", dir );
|
|
|
|
else sprintf ( fname , "./gb.conf" );
|
2016-04-29 14:29:06 +02:00
|
|
|
|
2014-10-06 21:35:54 -07:00
|
|
|
// try regular gb.conf then
|
2014-03-07 09:05:14 -08:00
|
|
|
f.set ( fname );
|
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
// make sure g_mem.maxMem is big enough temporarily
|
2015-08-14 12:58:54 -06:00
|
|
|
g_conf.m_maxMem = 8000000000; // 8gb temp
|
|
|
|
|
2014-06-10 12:29:50 -07:00
|
|
|
bool status = g_parms.setFromFile ( this , fname , NULL , OBJ_CONF );
|
2013-08-02 13:12:24 -07:00
|
|
|
|
2015-08-14 12:58:54 -06:00
|
|
|
if ( g_conf.m_maxMem < 10000000 ) g_conf.m_maxMem = 10000000;
|
|
|
|
|
2014-06-19 15:27:46 -07:00
|
|
|
// if not there, create it!
|
|
|
|
if ( ! status ) {
|
|
|
|
log("gb: Creating %s from defaults.",fname);
|
|
|
|
g_errno = 0;
|
|
|
|
// set to defaults
|
|
|
|
g_conf.reset();
|
|
|
|
// and save it
|
|
|
|
m_save = true;
|
|
|
|
save();
|
|
|
|
// clear errors
|
|
|
|
g_errno = 0;
|
|
|
|
status = true;
|
|
|
|
}
|
|
|
|
|
2015-08-14 12:58:54 -06:00
|
|
|
if ( ! g_mem.init ( ) ) return false;
|
2016-04-29 14:29:06 +02:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
// always turn this off
|
|
|
|
g_conf.m_testMem = false;
|
2016-04-29 14:29:06 +02:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
// and this, in case you forgot to turn it off
|
|
|
|
if ( g_conf.m_isLive ) g_conf.m_doConsistencyTesting = false;
|
2016-04-29 14:29:06 +02:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
// this off
|
|
|
|
g_conf.m_repairingEnabled = false;
|
2016-03-03 15:55:08 +01:00
|
|
|
|
2014-01-09 19:00:21 -08:00
|
|
|
// force on for now
|
|
|
|
g_conf.m_useStatsdb = true;
|
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
// hard-code disable this -- could be dangerous
|
2016-04-29 14:29:06 +02:00
|
|
|
g_conf.m_bypassValidation = true;
|
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
// this could too! (need this)
|
2014-01-09 17:29:18 -08:00
|
|
|
g_conf.m_allowScale = true;//false;
|
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
// . until we fix spell checker
|
|
|
|
// . the hosts splitting count isn't right and it just sends to like
|
|
|
|
// host #0 or something...
|
|
|
|
g_conf.m_doSpellChecking = false;
|
2015-03-08 20:36:13 -07:00
|
|
|
|
|
|
|
g_conf.m_forceIt = false;
|
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
// sanity check
|
2014-05-01 17:07:31 -07:00
|
|
|
if ( g_hostdb.m_indexSplits > MAX_SHARDS ) {
|
|
|
|
log("db: Increase MAX_SHARDS");
|
2016-06-20 12:30:26 +02:00
|
|
|
g_process.shutdownAbort(true);
|
2013-08-02 13:12:24 -07:00
|
|
|
}
|
2013-09-13 09:23:18 -07:00
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
// HACK: set this now
|
|
|
|
setRootIps();
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Conf::setRootIps ( ) {
|
|
|
|
// set m_numDns based on Conf::m_dnsIps[] array
|
2015-12-15 13:36:39 +01:00
|
|
|
int32_t i; for ( i = 0; i < MAX_DNSIPS ; i++ ) {
|
2013-08-02 13:12:24 -07:00
|
|
|
m_dnsPorts[i] = 53;
|
|
|
|
if ( ! g_conf.m_dnsIps[i] ) break;
|
|
|
|
}
|
|
|
|
m_numDns = i;
|
|
|
|
|
2015-12-15 15:09:11 +01:00
|
|
|
// fail back to public dns
|
|
|
|
const char *ipStr = PUBLICLY_AVAILABLE_DNS1;
|
2013-08-02 13:12:24 -07:00
|
|
|
if ( m_numDns == 0 ) {
|
2016-07-28 17:04:35 +02:00
|
|
|
m_dnsIps[0] = atoip( ipStr , strlen(ipStr) );
|
2013-08-02 13:12:24 -07:00
|
|
|
m_dnsPorts[0] = 53;
|
|
|
|
m_numDns = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// default this to off on startup for now until it works better
|
|
|
|
m_askRootNameservers = false;
|
2015-12-11 19:07:14 +01:00
|
|
|
|
2014-01-09 12:38:38 -08:00
|
|
|
// and return as well
|
|
|
|
return;
|
2013-08-02 13:12:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// . parameters can be changed on the fly so we must save Conf
|
|
|
|
bool Conf::save ( ) {
|
2016-04-29 14:21:21 +02:00
|
|
|
if ( ! m_save ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-08-21 18:07:07 -07:00
|
|
|
// fix so if we core in malloc/free we can still save conf
|
|
|
|
char fnbuf[1024];
|
|
|
|
SafeBuf fn(fnbuf,1024);
|
2014-07-29 10:02:43 -07:00
|
|
|
fn.safePrintf("%sgb.conf",g_hostdb.m_dir);
|
2016-04-29 14:21:21 +02:00
|
|
|
bool status = g_parms.saveToXml ( (char *)this , fn.getBufStart(), OBJ_CONF );
|
|
|
|
|
2013-08-02 13:12:24 -07:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
// . get the default collection based on hostname
|
|
|
|
// will look for the hostname in each collection for a match
|
|
|
|
// no match defaults to default collection
|
Fix conversion from string literal to 'char *' for Conf, Msg12, Msg3, MsgC, Parms, PingServer, Rdb, RdbBase, RdbBuckets, TcpServer, XmlDoc
2016-05-31 10:46:35 +02:00
|
|
|
const char *Conf::getDefaultColl ( char *hostname, int32_t hostnameLen ) {
|
2016-04-29 14:29:06 +02:00
|
|
|
if ( ! m_defaultColl || ! m_defaultColl[0] ) {
|
2013-12-08 16:44:37 -07:00
|
|
|
return "main";
|
2013-08-02 13:12:24 -07:00
|
|
|
}
|
2016-04-29 14:29:06 +02:00
|
|
|
|
|
|
|
// just use default coll for now to keep things simple
|
2013-08-02 13:12:24 -07:00
|
|
|
return m_defaultColl;
|
|
|
|
}
|