diff options
author | Patrick Murphy <patrick.muprphy@multitech.com> | 2020-04-13 13:24:41 -0500 |
---|---|---|
committer | Patrick Murphy <patrick.muprphy@multitech.com> | 2020-04-13 13:24:41 -0500 |
commit | f8ba84f1366cc4df61b8f16afd8ed872db8930cc (patch) | |
tree | 3c925b228d17188ad99bb86ebf0ce6f88bf89d7c /src/commission_func.cc | |
parent | f895e46a542d07fec1cdff621ff250b156f0069e (diff) | |
download | commissioning-f8ba84f1366cc4df61b8f16afd8ed872db8930cc.tar.gz commissioning-f8ba84f1366cc4df61b8f16afd8ed872db8930cc.tar.bz2 commissioning-f8ba84f1366cc4df61b8f16afd8ed872db8930cc.zip |
fcgi commissioning 1.0
Diffstat (limited to 'src/commission_func.cc')
-rw-r--r-- | src/commission_func.cc | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/src/commission_func.cc b/src/commission_func.cc new file mode 100644 index 0000000..10e47cf --- /dev/null +++ b/src/commission_func.cc @@ -0,0 +1,395 @@ +#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_pass).c_str(), "w"); + if (fpopen == NULL) { + syslog (LOG_ALERT, "popen for passwd failed to return a useful pointer"); + //handle error via logging, closing + } + parse_cmd= tmp_pass + '\n' + tmp_pass; + fputs(parse_cmd.c_str(), fpopen); + 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-uppasswd 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-uppasswd 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<AASID_LENGTH; i++) { + output += table[rand() % (table.length()-1)]; + } + return output; +} + +bool properInput(Json::Value jobj) { + bool aasid = false; + bool aasanswr = false; + bool usrname = false; + std::vector<std::string> 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 (getpwnam(name.c_str()) == NULL) { + 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; +}
\ No newline at end of file |