#include "commission_func.h" int begin_fcgi() { // Set up commissioning enviornment variables. bool parseJson, is_err, commissioning = false, complete = false; int popen_ret, atmpt_cntr = 0; Json::Reader reader; Json::Value j_post; Json::StyledWriter swriter; std::string posted, parse_cmd, parse_logger; std::string aasid = ""; std::string tmp_usrname = ""; std::string tmp_pass = ""; std::streambuf * cin_streambuf = std::cin.rdbuf(); std::streambuf * cout_streambuf = std::cout.rdbuf(); std::streambuf * cerr_streambuf = std::cerr.rdbuf(); FILE *fpopen; char fileread[MAX_GET]; //set up the syslog event openlog("commissioning.fcgi", LOG_PID | LOG_PERROR, LOG_LOCAL0); //set up fcgi environment FCGX_Request request; FCGX_Init(); FCGX_InitRequest(&request, 0, 0); //listen for requests while (FCGX_Accept_r(&request) == 0 && !complete) { // set streambuffers to fcgi request fcgi_streambuf cin_fcgi_streambuf(request.in); fcgi_streambuf cout_fcgi_streambuf(request.out); fcgi_streambuf cerr_fcgi_streambuf(request.err); std::cin.rdbuf(&cin_fcgi_streambuf); std::cout.rdbuf(&cout_fcgi_streambuf); std::cerr.rdbuf(&cerr_fcgi_streambuf); // receive data from POST posted = get_request_content(request); if (posted.length() == 0) { //standard output (check if commissioning is on) std::cout << confirmCommissioning(); } else { //receive POSTed Json data bool parseJson = reader.parse(posted, j_post); //error state if (!parseJson) { syslog (LOG_ALERT, "Received unparsible data"); std::cout << ERROR_PARSE; std::cout << "Content-type: text/plain" << "\r\n" << "Output : " << posted <<"\r\n"; //if sent data doesn't follow proper formatting } else if (!properInput(j_post)) { std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, true, aasid, ERR_MALDATA, AASTYPE_ERR); syslog (LOG_ALERT, "Received malformed user data entry"); //if we are not in the middle of a commissioning session } else if (!commissioning) { //if the user requests an illegal username if(!legalName(j_post["username"].asString())) { std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, true, aasid, ERR_ILLEGALUSRNAME, AASTYPE_ERR); syslog (LOG_ALERT, "Received request for unauthorized username"); } else { // start a new commissioning session commissioning = true; atmpt_cntr = 0; tmp_usrname = j_post["username"].asString(); aasid = gen_aasid(); //send confirmation message std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, false, aasid, MSG_NEWPASSWD, AASTYPE_QSTN); parse_cmd = "Received username: " + tmp_usrname + ", awaiting password request"; syslog (LOG_ALERT, parse_cmd.c_str()); } // we're in a commissioning session } else { if(tmp_pass == "") { //password request if(j_post["aasAnswer"].asString() == "") { //password was omitted std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, true, aasid, ERR_NOPASS, AASTYPE_ERR); parse_cmd = tmp_usrname + " password omission"; syslog (LOG_ALERT, parse_cmd.c_str()); }else if (j_post["aasID"] != aasid) { //aasID mismatch std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, true, aasid, ERR_BADAASID, AASTYPE_ERR); parse_cmd = tmp_usrname + " aasid does not match"; syslog (LOG_ALERT, parse_cmd.c_str()); } else if (j_post["username"].asString() != tmp_usrname) { //user ID mismatch std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, true, aasid, ERR_USRMISMATCH, AASTYPE_ERR); parse_cmd = tmp_usrname + " returned a mismatched username mid session"; syslog (LOG_ALERT, parse_cmd.c_str()); } else { //successful password request atmpt_cntr = 0; tmp_pass = j_post["aasAnswer"].asString(); std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, false, aasid, MSG_RETYPEPASS, AASTYPE_QSTN); parse_cmd = tmp_usrname + " successfuly requested a password. Awaiting verification"; syslog (LOG_ALERT, parse_cmd.c_str()); } } else { //password request if(j_post["aasAnswer"].asString() == "") { //password was omitted std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, true, aasid, ERR_NOPASS, AASTYPE_ERR); parse_cmd = tmp_usrname + " password omission"; }else if (j_post["aasID"] != aasid) { //aasID mismatch std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, true, aasid, ERR_BADAASID, AASTYPE_ERR); parse_cmd = tmp_usrname + " aasid does not match"; syslog (LOG_ALERT, parse_cmd.c_str()); } else if (j_post["username"].asString() != tmp_usrname) { //user ID mismatch std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, true, aasid, ERR_USRMISMATCH, AASTYPE_ERR); parse_cmd = tmp_usrname + " returned a mismatched username mid session"; syslog (LOG_ALERT, parse_cmd.c_str()); } else if (j_post["aasAnswer"].asString() != tmp_pass) { std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, true, aasid, ERR_PWMISMATCH, AASTYPE_ERR); parse_cmd = tmp_usrname + " verification attempt did not match"; syslog (LOG_ALERT, parse_cmd.c_str()); } else { //successful password request atmpt_cntr = 0; commissioning = false; std::cout << printMsg(commissioning, atmpt_cntr, tmp_pass, false, aasid, MSG_SUCCESS, AASTYPE_INFO); parse_cmd = tmp_usrname + " data entry successful. Creating user account"; syslog (LOG_ALERT, parse_cmd.c_str()); /****** * COMMISSIONING CODE * ***/ /****useradd****/ fpopen = popen(useradd_cmd_gen(tmp_usrname).c_str(), "r"); if (fpopen == NULL) { syslog (LOG_ALERT, "popen for useradd failed to return a useful pointer"); //handle error via logging, closing } while (fgets(fileread, MAX_GET, fpopen) != NULL) { printf("%s", fileread); } popen_ret = pclose(fpopen); if (popen_ret == -1) { syslog (LOG_ALERT, "pclose for useradd failed"); //handle error via logging, closing } /****passwd****/ fpopen = popen(passwd_cmd_gen(tmp_usrname).c_str(), "w"); if (fpopen == NULL) { syslog (LOG_ALERT, "popen for passwd failed to return a useful pointer"); //handle error via logging, closing } fprintf(fpopen, "%s\n", tmp_pass.c_str()); fprintf(fpopen, "%s\n", tmp_pass.c_str()); popen_ret = pclose(fpopen); if (popen_ret == -1) { syslog (LOG_ALERT, "pclose for passwd failed"); // handle error via logging, closing } /****mts-ubpasswd****/ fpopen = popen(POPEN_MTS_UBPW.c_str(), "w"); if (fpopen == NULL) { syslog (LOG_ALERT, "mts-ubpasswd for passwd failed to return a useful pointer"); //handle error via logging, closing } fputs(tmp_pass.c_str(), fpopen); popen_ret = pclose(fpopen); if (popen_ret == -1) { syslog (LOG_ALERT, "pclose for mts-ubpasswd failed"); //handle error via logging, closing } /***** * EMPTY TEMP VALS * *** * /****** * CLOSEOUTCODE * ****/ fpopen = popen(POPEN_CLOSEALL.c_str(), "r"); if (fpopen == NULL) { syslog (LOG_ALERT, "closeall routine failed to return a useful pointer"); //handle error via logging, closing } while (fgets(fileread, MAX_GET, fpopen) != NULL) { printf("%s", fileread); } popen_ret = pclose(fpopen); if (popen_ret == -1) { syslog (LOG_ALERT, "pclose for closeall routine failed "); //handle error via logging, closing } complete = true; } } } } } // restore stdio streambufs std::cin.rdbuf(cin_streambuf); std::cout.rdbuf(cout_streambuf); std::cerr.rdbuf(cerr_streambuf); return 0; } /*****message delivery function definitions ********************************************/ std::string confirmCommissioning() { std::string formatted_output; Json::Value output; Json::StyledWriter writer; output["code"] = 200; output["status"] = "success"; formatted_output = HEADER + writer.write(output) + "\n"; return formatted_output; } std::string printMsg(bool &is_commission, int &atmpt_cntr, std::string &pw, bool is_err, std::string aasid, std::string msg, std::string aastype) { std::string formatted_output, msg_output; Json::Value output; Json::StyledWriter writer; bool aasDone = false; int retries_left; //set aasDone if (aastype == MSG_SUCCESS) { aasDone = true; } //not commissioning yet. msg_output = msg; if (is_err) { msg_output += ": Please try again."; //mid commission attempt. if (is_commission) { atmpt_cntr++; retries_left = NUM_ATTEMPTS - atmpt_cntr; msg_output = msg + ": Retries left: " + std::to_string(retries_left); //commission attempts exhausted. if (retries_left <= 0) { atmpt_cntr = 0; is_commission = false; pw = ""; msg_output += ". Attempts exhausted. Please reattempt username."; } } } output["code"] = 200; output["result"]["aasDone"] = aasDone; output["result"]["aasID"] = aasid; output["result"]["aasMsg"] = msg_output; output["result"]["aasType"] = aastype; output["status"] = "success"; return HEADER + writer.write(output) + "\n"; } /******** recieve input function definitions *********************************/ std::string get_request_content(const FCGX_Request &request) { char * content_length_str = FCGX_GetParam("CONTENT_LENGTH", request.envp); unsigned long content_length = STDIN_MAX; if (content_length_str) { content_length = strtol(content_length_str, &content_length_str, 10); if (*content_length_str) { std::cerr << "Can't Parse 'CONTENT_LENGTH='" << FCGX_GetParam("CONTENT_LENGTH", request.envp) << "'. Consuming stdin up to " << STDIN_MAX << std::endl; } if (content_length > STDIN_MAX) { content_length = STDIN_MAX; } } else { // Do not read from stdin if CONTENT_LENGTH is missing content_length = 0; } char * content_buffer = new char[content_length]; std::cin.read(content_buffer, content_length); content_length = std::cin.gcount(); // Chew up any remaining stdin - this shouldn't be necessary // but is because mod_fastcgi doesn't handle it correctly. // ignore() doesn't set the eof bit in some versions of glibc++ // so use gcount() instead of eof()... do std::cin.ignore(1024); while (std::cin.gcount() == 1024); std::string content(content_buffer, content_length); delete [] content_buffer; return content; } std::string gen_aasid() { std::string output; std::string table = "ABCDEFGHIJKLMNOPQRSTUVWZYZ1234567890"; srand(time(0)); for (int i=0; i memberNames; std::string m_username = "username"; std::string m_aasid = "aasID"; std::string m_aasAnswr = "aasAnswer"; memberNames = jobj.getMemberNames(); for (int i=0; i < memberNames.size(); i++) { if (memberNames[i] == m_username) { usrname = true; } else if (memberNames[i] == m_aasid) { aasid = true; } else if (memberNames[i] == m_aasAnswr) { aasanswr = true; } } if (aasid && aasanswr && usrname) { return true; } return false; } /* TODO: expand list of legal and illegal names as needed */ bool legalName(std::string name) { /* std::string cmd = "/usr/bin/id -u \""; char *temp = NULL; std::string popen_out; */ if (name != "root") { syslog (LOG_ALERT, "Received a legal name request"); //the name is available return true; } syslog (LOG_ALERT, "Receives an illegal name request"); return false; } /*** generate command functions ***/ std::string passwd_cmd_gen(std::string pw) { std::string cmd = "/usr/bin/passwd \""; cmd +=pw; cmd +="\""; return cmd; } std::string useradd_cmd_gen(std::string usr) { std::string cmd = "/usr/sbin/useradd -U -m -G sudo,dialout,disk -s /bin/bash -- \""; cmd +=usr; cmd +="\""; return cmd; }