void ESP_MQTTLogger::_mqttSetup() { if (!_authenticate()){ _server->send(401, "text/plain", "Unauthorised"); return; } if(_server->hasArg("mqtt_url")) { if (!_parseMQTTUrl(_server->arg("mqtt_url"))){ _server->send(400, "text/plain", "Invalid URL"); return; } _mqttUrl = _server->arg("mqtt_url"); #ifdef MQTT_LOGGER_DEBUG DEBUG_OUTPUT.print("configuring mqttUrl: "); DEBUG_OUTPUT.println(_mqttUrl); #endif if (!_saveMQTTUrl()) { _server->send(500, "text/plain", "Save configuration failed"); } _server->send(200, "text/plain", "OK"); return; } _server->send(400, "text/plain", ""); }
void NetworkInterfaceASIO::_runIsMaster(AsyncOp* op) { // We use a legacy builder to create our ismaster request because we may // have to communicate with servers that do not support OP_COMMAND rpc::LegacyRequestBuilder requestBuilder{}; requestBuilder.setDatabase("admin"); requestBuilder.setCommandName("isMaster"); requestBuilder.setMetadata(rpc::makeEmptyMetadata()); requestBuilder.setCommandArgs(BSON("isMaster" << 1)); // Set current command to ismaster request and run auto beginStatus = op->beginCommand(std::move(*(requestBuilder.done()))); if (!beginStatus.isOK()) { return _completeOperation(op, beginStatus); } // Callback to parse protocol information out of received ismaster response auto parseIsMaster = [this, op]() { auto swCommandReply = op->command()->response(rpc::Protocol::kOpQuery, now()); if (!swCommandReply.isOK()) { return _completeOperation(op, swCommandReply.getStatus()); } auto commandReply = std::move(swCommandReply.getValue()); if (_hook) { // Run the validation hook. auto validHost = callNoexcept( *_hook, &NetworkConnectionHook::validateHost, op->request().target, commandReply); if (!validHost.isOK()) { return _completeOperation(op, validHost); } } auto protocolSet = rpc::parseProtocolSetFromIsMasterReply(commandReply.data); if (!protocolSet.isOK()) return _completeOperation(op, protocolSet.getStatus()); op->connection().setServerProtocols(protocolSet.getValue()); // Set the operation protocol auto negotiatedProtocol = rpc::negotiate(op->connection().serverProtocols(), op->connection().clientProtocols()); if (!negotiatedProtocol.isOK()) { return _completeOperation(op, negotiatedProtocol.getStatus()); } op->setOperationProtocol(negotiatedProtocol.getValue()); return _authenticate(op); }; _asyncRunCommand(op->command(), [this, op, parseIsMaster](std::error_code ec, size_t bytes) { _validateAndRun(op, ec, std::move(parseIsMaster)); }); }
void NetworkInterfaceASIO::_runIsMaster(AsyncOp* op) { // We use a legacy builder to create our ismaster request because we may // have to communicate with servers that do not support OP_COMMAND rpc::LegacyRequestBuilder requestBuilder{}; requestBuilder.setDatabase("admin"); requestBuilder.setCommandName("isMaster"); requestBuilder.setMetadata(rpc::makeEmptyMetadata()); requestBuilder.setCommandArgs(BSON("isMaster" << 1)); // Set current command to ismaster request and run auto& cmd = op->beginCommand(std::move(*(requestBuilder.done()))); // Callback to parse protocol information out of received ismaster response auto parseIsMaster = [this, op]() { try { auto commandReply = rpc::makeReply(&(op->command().toRecv())); BSONObj isMasterReply = commandReply->getCommandReply(); auto protocolSet = rpc::parseProtocolSetFromIsMasterReply(isMasterReply); if (!protocolSet.isOK()) return _completeOperation(op, protocolSet.getStatus()); op->connection().setServerProtocols(protocolSet.getValue()); // Set the operation protocol auto negotiatedProtocol = rpc::negotiate(op->connection().serverProtocols(), op->connection().clientProtocols()); if (!negotiatedProtocol.isOK()) { return _completeOperation(op, negotiatedProtocol.getStatus()); } op->setOperationProtocol(negotiatedProtocol.getValue()); // Advance the state machine return _authenticate(op); } catch (...) { // makeReply will throw if the reply was invalid. return _completeOperation(op, exceptionToStatus()); } }; _asyncRunCommand(&cmd, [this, op, parseIsMaster](std::error_code ec, size_t bytes) { _validateAndRun(op, ec, std::move(parseIsMaster)); }); }
bool CmdAuthenticate::run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { mutablebson::Document cmdToLog(cmdObj, mutablebson::Document::kInPlaceDisabled); redactForLogging(&cmdToLog); log() << " authenticate db: " << dbname << " " << cmdToLog << endl; UserName user(cmdObj.getStringField("user"), dbname); if (Command::testCommandsEnabled && user.getDB() == "admin" && user.getUser() == internalSecurity.user->getName().getUser()) { // Allows authenticating as the internal user against the admin database. This is to // support the auth passthrough test framework on mongos (since you can't use the local // database on a mongos, so you can't auth as the internal user without this). user = internalSecurity.user->getName(); } std::string mechanism = cmdObj.getStringField("mechanism"); if (mechanism.empty()) { mechanism = "MONGODB-CR"; } Status status = _authenticate(mechanism, user, cmdObj); audit::logAuthentication(ClientBasic::getCurrent(), mechanism, user, status.code()); if (!status.isOK()) { log() << "Failed to authenticate " << user << " with mechanism " << mechanism << ": " << status; if (status.code() == ErrorCodes::AuthenticationFailed) { // Statuses with code AuthenticationFailed may contain messages we do not wish to // reveal to the user, so we return a status with the message "auth failed". appendCommandStatus(result, Status(ErrorCodes::AuthenticationFailed, "auth failed")); } else { appendCommandStatus(result, status); } return false; } result.append("dbname", user.getDB()); result.append("user", user.getUser()); return true; }
bool CmdAuthenticate::run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) { mutablebson::Document cmdToLog(cmdObj, mutablebson::Document::kInPlaceDisabled); redactForLogging(&cmdToLog); log() << " authenticate db: " << dbname << " " << cmdToLog << endl; UserName user(cmdObj.getStringField("user"), dbname); std::string mechanism = cmdObj.getStringField("mechanism"); if (mechanism.empty()) { mechanism = "MONGODB-CR"; } Status status = _authenticate(mechanism, user, cmdObj); audit::logAuthentication(ClientBasic::getCurrent(), mechanism, user, status.code()); if (!status.isOK()) { log() << "Failed to authenticate " << user << " with mechanism " << mechanism << ": " << status; if (status.code() == ErrorCodes::AuthenticationFailed) { // Statuses with code AuthenticationFailed may contain messages we do not wish to // reveal to the user, so we return a status with the message "auth failed". appendCommandStatus(result, Status(ErrorCodes::AuthenticationFailed, "auth failed")); } else { appendCommandStatus(result, status); } return false; } result.append("dbname", user.getDB()); result.append("user", user.getUser()); return true; }
void NetworkInterfaceASIO::_runIsMaster(AsyncOp* op) { // We use a legacy builder to create our ismaster request because we may // have to communicate with servers that do not support OP_COMMAND rpc::LegacyRequestBuilder requestBuilder{}; requestBuilder.setDatabase("admin"); requestBuilder.setCommandName("isMaster"); BSONObjBuilder bob; bob.append("isMaster", 1); bob.append("hangUpOnStepDown", false); const auto versionString = VersionInfoInterface::instance().version(); ClientMetadata::serialize(_options.instanceName, versionString, &bob); if (Command::testCommandsEnabled) { // Only include the host:port of this process in the isMaster command request if test // commands are enabled. mongobridge uses this field to identify the process opening a // connection to it. StringBuilder sb; sb << getHostName() << ':' << serverGlobalParams.port; bob.append("hostInfo", sb.str()); } op->connection().getCompressorManager().clientBegin(&bob); if (WireSpec::instance().isInternalClient) { WireSpec::appendInternalClientWireVersion(WireSpec::instance().outgoing, &bob); } requestBuilder.setCommandArgs(bob.done()); requestBuilder.setMetadata(rpc::makeEmptyMetadata()); // Set current command to ismaster request and run auto beginStatus = op->beginCommand(requestBuilder.done(), op->request().target); if (!beginStatus.isOK()) { return _completeOperation(op, beginStatus); } // Callback to parse protocol information out of received ismaster response auto parseIsMaster = [this, op]() { auto swCommandReply = op->command()->response(op, rpc::Protocol::kOpQuery, now()); if (!swCommandReply.isOK()) { return _completeOperation(op, swCommandReply); } auto commandReply = std::move(swCommandReply); // Ensure that the isMaster response is "ok:1". auto commandStatus = getStatusFromCommandResult(commandReply.data); if (!commandStatus.isOK()) { return _completeOperation(op, commandStatus); } auto protocolSet = rpc::parseProtocolSetFromIsMasterReply(commandReply.data); if (!protocolSet.isOK()) return _completeOperation(op, protocolSet.getStatus()); auto validateStatus = rpc::validateWireVersion(WireSpec::instance().outgoing, protocolSet.getValue().version); if (!validateStatus.isOK()) { warning() << "remote host has incompatible wire version: " << validateStatus; return _completeOperation(op, validateStatus); } op->connection().setServerProtocols(protocolSet.getValue().protocolSet); invariant(op->connection().clientProtocols() != rpc::supports::kNone); // Set the operation protocol auto negotiatedProtocol = rpc::negotiate(op->connection().serverProtocols(), op->connection().clientProtocols()); if (!negotiatedProtocol.isOK()) { // Add relatively verbose logging here, since this should not happen unless we are // mongos and we try to connect to a node that doesn't support OP_COMMAND. warning() << "failed to negotiate protocol with remote host: " << op->request().target; warning() << "request was: " << redact(op->request().cmdObj); warning() << "response was: " << redact(commandReply.data); auto clientProtos = rpc::toString(op->connection().clientProtocols()); if (clientProtos.isOK()) { warning() << "our (client) supported protocols: " << clientProtos.getValue(); } auto serverProtos = rpc::toString(op->connection().serverProtocols()); if (serverProtos.isOK()) { warning() << "remote server's supported protocols:" << serverProtos.getValue(); } return _completeOperation(op, negotiatedProtocol.getStatus()); } op->setOperationProtocol(negotiatedProtocol.getValue()); op->connection().getCompressorManager().clientFinish(commandReply.data); if (_hook) { // Run the validation hook. auto validHost = callNoexcept( *_hook, &NetworkConnectionHook::validateHost, op->request().target, commandReply); if (!validHost.isOK()) { return _completeOperation(op, validHost); } } return _authenticate(op); }; _asyncRunCommand(op, [this, op, parseIsMaster](std::error_code ec, size_t bytes) { _validateAndRun(op, ec, std::move(parseIsMaster)); }); }
static char * authdes_ezdecode(const char *inmsg, int len) { struct rpc_msg msg; char cred_area[MAX_AUTH_BYTES]; char verf_area[MAX_AUTH_BYTES]; char *temp_inmsg; struct svc_req r; bool_t res0, res1; XDR xdr; SVCXPRT xprt; temp_inmsg = malloc(len); memmove(temp_inmsg, inmsg, len); memset((char *) &msg, 0, sizeof(msg)); memset((char *) &r, 0, sizeof(r)); memset(cred_area, 0, sizeof(cred_area)); memset(verf_area, 0, sizeof(verf_area)); msg.rm_call.cb_cred.oa_base = cred_area; msg.rm_call.cb_verf.oa_base = verf_area; why = AUTH_FAILED; xdrmem_create(&xdr, temp_inmsg, len, XDR_DECODE); if ((r.rq_clntcred = malloc(MAX_AUTH_BYTES)) == NULL) goto bad1; r.rq_xprt = &xprt; /* decode into msg */ res0 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_cred)); res1 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_verf)); if (!(res0 && res1)) goto bad2; /* do the authentication */ r.rq_cred = msg.rm_call.cb_cred; /* read by opaque stuff */ if (r.rq_cred.oa_flavor != AUTH_DES) { why = AUTH_TOOWEAK; goto bad2; } #ifdef SVR4 if ((why = __authenticate(&r, &msg)) != AUTH_OK) { #else if ((why = _authenticate(&r, &msg)) != AUTH_OK) { #endif goto bad2; } return (((struct authdes_cred *) r.rq_clntcred)->adc_fullname.name); bad2: free(r.rq_clntcred); bad1: return ((char *) 0); /* ((struct authdes_cred *) NULL); */ } static XID rpc_id = (XID) ~0L; static Bool CheckNetName(unsigned char *addr, short len, pointer closure) { return (len == strlen((char *) closure) && strncmp((char *) addr, (char *) closure, len) == 0); } static char rpc_error[MAXNETNAMELEN + 50]; _X_HIDDEN XID SecureRPCCheck(unsigned short data_length, const char *data, ClientPtr client, const char **reason) { char *fullname; if (rpc_id == (XID) ~0L) { *reason = "Secure RPC authorization not initialized"; } else { fullname = authdes_ezdecode(data, data_length); if (fullname == (char *) 0) { snprintf(rpc_error, sizeof(rpc_error), "Unable to authenticate secure RPC client (why=%d)", why); *reason = rpc_error; } else { if (ForEachHostInFamily(FamilyNetname, CheckNetName, fullname)) return rpc_id; snprintf(rpc_error, sizeof(rpc_error), "Principal \"%s\" is not authorized to connect", fullname); *reason = rpc_error; } } return (XID) ~0L; }
void svc_getreq_common (const int fd) { enum xprt_stat stat; struct rpc_msg msg; register SVCXPRT *xprt; char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE]; msg.rm_call.cb_cred.oa_base = cred_area; msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); xprt = xports[fd]; /* Do we control fd? */ if (xprt == NULL) return; /* now receive msgs from xprtprt (support batch calls) */ do { if (SVC_RECV (xprt, &msg)) { /* now find the exported program and call it */ struct svc_callout *s; struct svc_req r; enum auth_stat why; rpcvers_t low_vers; rpcvers_t high_vers; int prog_found; r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]); r.rq_xprt = xprt; r.rq_prog = msg.rm_call.cb_prog; r.rq_vers = msg.rm_call.cb_vers; r.rq_proc = msg.rm_call.cb_proc; r.rq_cred = msg.rm_call.cb_cred; /* first authenticate the message */ /* Check for null flavor and bypass these calls if possible */ if (msg.rm_call.cb_cred.oa_flavor == AUTH_NULL) { r.rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; r.rq_xprt->xp_verf.oa_length = 0; } else if ((why = _authenticate (&r, &msg)) != AUTH_OK) { svcerr_auth (xprt, why); goto call_done; } /* now match message with a registered service */ prog_found = FALSE; low_vers = 0 - 1; high_vers = 0; for (s = svc_head; s != NULL_SVC; s = s->sc_next) { if (s->sc_prog == r.rq_prog) { if (s->sc_vers == r.rq_vers) { (*s->sc_dispatch) (&r, xprt); goto call_done; } /* found correct version */ prog_found = TRUE; if (s->sc_vers < low_vers) low_vers = s->sc_vers; if (s->sc_vers > high_vers) high_vers = s->sc_vers; } /* found correct program */ } /* if we got here, the program or version is not served ... */ if (prog_found) svcerr_progvers (xprt, low_vers, high_vers); else svcerr_noprog (xprt); /* Fall through to ... */ } call_done: if ((stat = SVC_STAT (xprt)) == XPRT_DIED) { SVC_DESTROY (xprt); break; } } while (stat == XPRT_MOREREQS); }
void NetworkInterfaceASIO::_sslHandshake(AsyncOp* op) { // TODO: Implement asynchronous SSL, SERVER-19221 _authenticate(op); }
void svc_getreq_common(int fd) { enum xprt_stat stat; struct rpc_msg msg; int prog_found; u_long low_vers; u_long high_vers; struct svc_req r; SVCXPRT *xprt; char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; msg.rm_call.cb_cred.oa_base = cred_area; msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); /* sock has input waiting */ xprt = xports[fd]; if (xprt == NULL) /* But do we control the fd? */ return; /* now receive msgs from xprtprt (support batch calls) */ do { if (SVC_RECV(xprt, &msg)) { /* find the exported program and call it */ struct svc_callout *s; enum auth_stat why; r.rq_xprt = xprt; r.rq_prog = msg.rm_call.cb_prog; r.rq_vers = msg.rm_call.cb_vers; r.rq_proc = msg.rm_call.cb_proc; r.rq_cred = msg.rm_call.cb_cred; /* first authenticate the message */ if ((why= _authenticate(&r, &msg)) != AUTH_OK) { svcerr_auth(xprt, why); goto call_done; } /* now match message with a registered service*/ prog_found = FALSE; low_vers = (u_long) -1; high_vers = 0; for (s = svc_head; s != NULL; s = s->sc_next) { if (s->sc_prog == r.rq_prog) { if (s->sc_vers == r.rq_vers) { (*s->sc_dispatch)(&r, xprt); goto call_done; } /* found correct version */ prog_found = TRUE; if (s->sc_vers < low_vers) low_vers = s->sc_vers; if (s->sc_vers > high_vers) high_vers = s->sc_vers; } /* found correct program */ } /* * if we got here, the program or version * is not served ... */ if (prog_found) svcerr_progvers(xprt, low_vers, high_vers); else svcerr_noprog(xprt); /* Fall through to ... */ } call_done: if ((stat = SVC_STAT(xprt)) == XPRT_DIED){ SVC_DESTROY(xprt); break; } } while (stat == XPRT_MOREREQS); }
int main(int argc, char *argv[]) { const char *program_name; char *service, *user; int fd; uid_t uid; uid = getuid(); /* * Make sure standard file descriptors are connected. */ while ((fd = open("/dev/null", O_RDWR)) <= 2) ; close(fd); /* * Get the program name */ if (argc == 0) program_name = "hawk_chkpwd"; else if ((program_name = strrchr(argv[0], '/')) != NULL) program_name++; else program_name = argv[0]; /* * Catch or ignore as many signal as possible. */ setup_signals(); /* * Check argument list */ if (argc != 3) { _log_err(LOG_NOTICE, "Bad number of arguments (%d)", argc); return UNIX_FAILED; } /* * Get the service name and do some sanity checks on it */ service = argv[1]; if (!sane_pam_service(service)) { _log_err(LOG_ERR, "Illegal service name '%s'", service); return UNIX_FAILED; } /* * Discourage users messing around (fat chance) */ if (isatty(STDIN_FILENO) && uid != 0) { _log_err(LOG_NOTICE, "Inappropriate use of Unix helper binary [UID=%d]", uid); fprintf(stderr, "This binary is not designed for running in this way\n" "-- the system administrator has been informed\n"); sleep(10); /* this should discourage/annoy the user */ return UNIX_FAILED; } /* * determine the caller's user name */ user = getuidname(uid); if (strcmp(user, argv[2])) { /* Discourage use of this program as a * password cracker */ if (uid != 0 && strcmp(user, HACLUSTER)) sleep(5); user = argv[2]; } if (!in_haclient_grp(user)) { _log_err(LOG_NOTICE, "Failed to authenticate user '%s' (not in group '%s')", user, HACLIENT); return UNIX_FAILED; } return _authenticate(service, user); }