/*************************************************************************** * Copyright (C) 2005 by Christof Donat * * cdonat@gmx.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "configfile.h" #include "logger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using std::ostringstream; using std::istringstream; using std::ifstream; using std::fstream; using std::string; using boost::lexical_cast; using boost::bad_lexical_cast; ConfigFileFinder::ConfigFileFinder(Transaction& t): vector() { try { boost::filesystem::path general("/etc/hsadminc.conf"); if( boost::filesystem::exists(general) && !boost::filesystem::is_directory(general) ) this->loadFile(general.native()); } catch(boost::filesystem::filesystem_error) {} string priv = getenv("HOME"); try { boost::filesystem::path p( priv + "/.hsadmin.conf"); if( boost::filesystem::exists(p) && !boost::filesystem::is_directory(p) ) this->loadFile(p.native()); } catch(boost::filesystem::filesystem_error) {} shared_ptr params = t.getParsed(); if( params->m_addConfigFile != "" ) try { boost::filesystem::path c( params->m_addConfigFile); if( boost::filesystem::exists(c) && !boost::filesystem::is_directory(c) ) this->loadFile(c.native()); } catch(boost::filesystem::filesystem_error) {} } void ConfigFileFinder::loadFile(string filename) { ifstream file(filename.c_str(),std::ios::in); ostringstream reader; reader << file.rdbuf(); string *tmp = new string(reader.str()); this->insert(this->end(),tmp); } void ConfigFileParser::parse(string& text) { vector lines; config * current = &(this->basic); vector configs; boost::split(lines,text,boost::is_any_of("\n")); if( current->pattern != ".*" ) { current->pattern = ".*"; current->ticketcommand = "hsadmint \\0"; current->server = "http://localhost:7777/RPC2"; current->shell = "/bin/sh"; current->askpass = false; } for( vector::iterator i = lines.begin(); i != lines.end(); i++ ) { string& line = *i; // ignore coments and empty lines boost::trim_left(line); if( line[0] == '#' || line == "" ) continue; // is this a section? if( line[0] == '[' ) { line.erase(0,1); line.erase(line.rfind(']')); if( current != &(this->basic) ) { configs.insert(configs.end(),*current); delete(current); } current = new config; *current = this->basic; current->pattern = line; } else { string::size_type equals = line.find('='); string name = boost::trim_copy(line.substr(0,equals)); string value = boost::trim_copy(line.substr(equals+1)); // trim name and value boost::trim(name); boost::trim(value); if( name == "ticket" ) current->ticketcommand = value; else if( name == "server" ) current->server = value; else if( name == "shell" ) current->shell = value; else if( name == "askpass" && value == "true" ) current->askpass = true; else if( name == "askpass" && value == "false" ) current->askpass = false; } } if( current != &(this->basic) ) { configs.insert(configs.end(),*current); delete(current); } this->configs.insert(this->configs.begin(),configs.begin(),configs.end()); } string ConfigFileParser::replaceStringMatches(string &userpattern, string username, string content) { if( username == "" ) { char* u = (char*)malloc(L_cuserid+1);; cuserid(u); if( u != 0 ) username = u; } boost::regex pattern(userpattern); boost::cmatch results; if( !boost::regex_match(username.c_str(),results,pattern) ) return content; for(int j = 0; j < results.size(); j++) { ostringstream p; p << "^\\\\" << j << "|([^\\\\])\\\\" << j; boost::regex pat(p.str()); string replace = "$1"; if( results[j].matched ) for( const char* i = results[j].first; i != results[j].second; i++ ) replace += *i; content = boost::regex_replace(content,pat,replace); } return content; } string ConfigFileParser::getTicket(string &username) { string ticketstring = ""; config cfg = this->getConfig(username); string command = cfg.getTicketcommand(username); Logger::log(Logger::DEBUG,"use '"+command+"' as command"); pid_t pid; pid_t parentpid = getpid(); int cmdout[2]; if(pipe(cmdout) || (pid=fork()) == -1) return ""; if(!pid) { close(1); close(cmdout[0]); dup(cmdout[1]); //command = cfg.shell+" -c \""+command+"\""; // this should never return. execlp(cfg.shell.c_str(),cfg.shell.c_str(),"-c",command.c_str(),(char*)0); // if we have reached this something has gone wrong. string msg = Logger::getMessageFormatString(Logger::ErrorWithTicketCommand); boost::format fmt(msg); fmt % cfg.shell % command % Logger::getErrnoMessage(errno); Logger::log(Logger::FATAL,fmt.str()); exit(-1); } int status; waitpid(pid,&status,0); close(cmdout[1]); // check if ticket has been successfully generated if( !WIFEXITED(status) || WEXITSTATUS(status) ) exit(WEXITSTATUS(status)); char buf[257]; bzero(buf,257); errno = 0; int i = 0; while( (i = read(cmdout[0],buf,256)) != 0 ) { if( i < 0 ) { if( errno == EAGAIN ) { usleep(20); continue; } else if( errno == EINTR ) continue; else { string msg = Logger::getMessageFormatString(Logger::ErrorReadingTicket); boost::format fmt(msg); fmt % Logger::getErrnoMessage(errno); Logger::log(Logger::FATAL,fmt.str()); exit(-1); } errno = 0; } ticketstring += buf; if( strlen(buf) < i ) break; bzero(buf,257); } return ticketstring; } ConfigFileParser::config &ConfigFileParser::getConfig(string &username) { if( username == "" ) return basic; for( vector::iterator i = configs.begin(); i != configs.end(); i++ ) { boost::regex pat(i->pattern); if(boost::regex_match(username,pat)) return *i; } return basic; }