void telnet_console_connection::redisplay_input() { writeclient("\r"); writeclient(prompt.c_str()); writeclient(inputbuf.c_str()); input_is_updated = true; }
bool telnet_console_connection::authenticate(const char *in) { bool denied = false; std::string password; writeclient("\r\n"); authenticate_state++; if (authenticate_state == WaitingPassword) { username = in; set_prompt("Password: "******"*") { authenticate_state++; } } } if (denied) { clearline(); writeclient("Your connection is not permited. Contact the system administrator.\r\n"); if (console->should_log(VERBOSE)) console->log().xprintf("(CONSOLE) denied connection" " from %{Addr}\n", c_peeraddr); console->release_connection(this); return false; } else if (authenticate_state == GotAllData) { writeclient("\r\n"); g_mrd->show_mrd_version(_output); _output.newl(); set_prompt("# "); should_echo = true; } return true; }
PROTO int send_date(void) { struct timeval tv; struct tm *ptm; char timestr[40]; gettimeofday(&tv,NULL); ptm = gmtime(&tv.tv_sec); strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S",ptm); return writeclient(client,"111 %s\r\n",timestr); }
bool telnet_console_connection::process_line(const char *in) { conn_timer.restart(); if (authenticate_state < GotAllData) { return authenticate(in); } if (should_echo) writeclient("\r\n"); bool res = console_connection::process_line(in); if (res) show_prompt(); history.push_back(in); history_pos = history.size(); return res; }
PROTO int cmdauthinfo(char *args) { char subcmd[17], subcmdargs[65]; USER *newuser; PROFILE *oldprf; PROFILE *newprf; int change_profile; AUTHRESULT *authres; sscanf (args, "%16[^\r\n\t ] %64[^\r\n]", subcmd, subcmdargs); if ( client->authenticated ) return swriteclient(client, MSG_AUTH_TWICE); if (!strcasecmp(subcmd,"user")) { if (client->authenticated && strncmp(client->username, subcmdargs, 64)) return swriteclient (client, MSG_AUTH_TWICE); if ( client->vhost->AddSuffix[0] != '\0' ) { snprintf(client->username, MAX_USERPASS-1, "%s@%s", subcmdargs, client->vhost->AddSuffix); } else { strncpy(client->username, subcmdargs, MAX_USERPASS-1); } } else if ( !strcasecmp(subcmd, "pass") ) { strncpy(client->password, subcmdargs, MAX_USERPASS-1); } else { return swriteclient(client, MSG_AUTH_UNKNOWN); } if ( client->username[0] == 0 || client->password[0] == 0 ) return swriteclient(client, MSG_MOREAUTHREQ); client->auth = getauth(client->username); if ( (authres=new_authresult(client)) == NULL ) return swriteclient(client, MSG_AUTH_NOMEM); void (*authmod)() = find_auth_mod(client->auth->auth->lib); if (!authmod) { CLEARPASS syslog(LOG_ERR, "Can't find authmap: %s", client->auth->auth->lib); swriteclient(client, MSG_AUTH_ERR); return 0; } client->authenticated = 0; (*authmod)(authres, &cfg, client->auth->auth->args); CLEARPASS if ( authres->authenticated == true ) { semlock_lock(master->semid); client->authenticated++; if ( authres->logname != NULL ) strcpy(client->logname, authres->logname); /* auth module specified profile */ if ( authres->profile != NULL ) { if ( (newprf = find_user_profile(client->username)) == NULL ) if ( (newprf=getprofile(authres->profile)) == NULL ) { client->authenticated--; semlock_unlock(master->semid); syslog(LOG_ERR, "Missing profile information from authenticator, rejecting user %s", authres->username); swriteclient(client, MSG_AUTH_ERR); free_authresult(authres); return 0; } } else { newprf = client->auth->profile; } PROFILE *p; if ( (p = prof_iplookup(newprf, client->addr.sin_addr)) != NULL ) newprf = p; if ( ! nullstr(newprf->Disabled) ) { client->authenticated--; semlock_unlock(master->semid); if ( cfg.LogAuthInfo ) syslog(LOG_NOTICE, "%s: authinfo login: %s result: 480 %s", client->hostname, authres->username, newprf->Disabled); return writeclient(client, "482 %s", newprf->Disabled); } /* Check and verify we are allowed in our new profile */ change_profile = 0; oldprf = client->profile; if ( client->profile != newprf ) { if ( newprf->connections > newprf->MaxConnections ) { client->authenticated--; semlock_unlock(master->semid); if ( cfg.LogAuthInfo ) syslog(LOG_NOTICE, "%s: authinfo login: %s result: %s", client->hostname, authres->username, MSG_AUTH_TOOMANYCON); return swriteclient(client, MSG_AUTH_TOOMANYCON); } else if ( newprf->numusers > newprf->MaxUsers ) { client->authenticated--; semlock_unlock(master->semid); if ( cfg.LogAuthInfo ) syslog(LOG_NOTICE, "%s: authinfo login: %s result: %s", client->hostname, authres->username, MSG_AUTH_TOOMANYUSR); return swriteclient(client, MSG_AUTH_TOOMANYUSR); } else { change_profile = 1; } } /* Find our other connections from this user to see if we are allowed */ newuser = find_user(client->username, newprf); if ( newuser != client->user && newuser != NULL ) { if ( newuser->connections > newprf->MaxUserConcurrent ) { client->authenticated--; drop_user(newuser->id, newprf); semlock_unlock(master->semid); sleep(cfg.RetryDelay); if ( cfg.LogAuthInfo ) syslog(LOG_NOTICE, "%s: authinfo login: %s result: %s", client->hostname, authres->username, MSG_AUTH_USERFULL); free_authresult(authres); return swriteclient(client, MSG_AUTH_USERFULL); } } if ( newuser == NULL ) syslog(LOG_ERR, "newuser == NULL"); /* check number of different connected hosts from new user */ int maxhosts = newprf->ASMaxHosts; int maxconns = newprf->ASMaxConns; if ( maxconns > 0 || maxhosts > 0 ) { char httpresult[2048]; semlock_unlock(master->semid); if ( ! check_http_accountsharing(client->username, client->hostname, maxhosts, maxconns, newprf->Name, httpresult) ) { syslog(LOG_DEBUG, "HTTP account sharing returned false. maxhosts=%d, maxconns=%d, user=%s, host=%s, newprf=%s, result=%s", maxhosts, maxconns, client->username, client->hostname, newprf->Name, httpresult); semlock_lock(master->semid); client->authenticated--; drop_user(newuser->id, newprf); semlock_unlock(master->semid); sleep(cfg.RetryDelay); free_authresult(authres); return writeclient(client, "482 %s", httpresult); } semlock_lock(master->semid); } if ( change_profile == 1 ) { if ( client->profile->connections == 0 ) syslog(LOG_ERR, "Trying to drop 0 connections profile from auth: %s", client->profile->Name); else client->profile->connections--; client->profile = newprf; client->profile->connections++; } drop_user(client->user->id, oldprf); client->user = newuser; client->user->bytesleft = authres->bytes; // client->initbytes; client->posting = authres->posting; if ( authres->userkbit > 0 ) client->user->MaxUserBPS = authres->userkbit * 1000 / 8; else client->user->MaxUserBPS = client->profile->MaxUserBPS; if ( authres->timeleft > 0 ) { client->user->timeleft = authres->timeleft; } if ( authres->readpat ) { strcpy(client->user->readpat, authres->readpat); } if ( authres->postpat ) { strcpy(client->user->postpat, authres->postpat); } // syslog(LOG_DEBUG, "%s: assigning-change %s userkey %s", client->hostname, client->profile->Name, client->user->key); /* init ratelimiter */ init_ratelimiter(client); semlock_unlock(master->semid); } if ( cfg.LogAuthInfo ) syslog(LOG_NOTICE, "%s: authinfo login: %s result: %s", client->hostname, authres->username, authres->message ? authres->message : "UNKNOWN"); swriteclient(client, authres->message ? authres->message : MSG_AUTH_ERR); free_authresult(authres); return 0; }
PROTO int group(const char *group, char nogroupecho) { char b[MAX_SERVERRSP]; ACTIVE *newgroup; SERVER *svr; CLEARBUF if ( nullstr(group) ) { swriteclient(client,"500 You must select a group\r\n"); return 1; } /* only change group if it has changed */ if ( client->group == NULL || strcmp(client->group->newsgroup, group) != 0 ) { /* check for read permission */ if ( ! match_expression((unsigned char *)group , (unsigned char *)getwildmat(client->user->readpat) , 0) ) { if ( ! nogroupecho ) swriteclient(client, MSG_NOSUCHGROUP); return 1; } /* find and load our new group */ if ( (newgroup = getgroup(group)) == NULL ) { if ( ! nogroupecho ) swriteclient(client, MSG_NOSUCHGROUP); return 1; } if ( (svr=getserver(newgroup->server)) == NULL ) return swriteclient(client, "500 Cant find server for group\r\n"); /* disconnect first if we have to change server */ if ( client->groupserver != NULL && client->connected == 1 && strcmp(svr->Groups, client->groupserver->Groups) != 0 ) { disconnect_server(client); } /* close group and reconnect */ closegroup(); client->group = newgroup; switch ( connect_groupserver(client, svr->Name) ) { case CONNECT_ERR: return swriteclient(client, "500 Error selecting server\r\n"); case CONNECT_DOWN: sleep(cfg.DownDelay); return writeclient(client, MSG_SERVER_DOWN); default: break; } /* reset by connect_groupserver (via disconnect_server FIXME) */ client->group = newgroup; client->groups++; } if ( ! writeserver(client, "GROUP %s\r\n", group) ) return -1; if ( ! readserver(client, b, MAX_SERVERRSP-1) ) return -1; syslog(LOG_NOTICE, "%s: group %s", client->hostname, group); if ( ! nogroupecho ) return swriteclient(client,b); return 0; }
void telnet_console_connection::flushed(const char *str, bool newline) { writeclient(str); if (newline) writeclient("\r\n"); }
void telnet_console_connection::show_prompt() { clearline(); writeclient(prompt.c_str()); }
bool telnet_console_connection::tabcomplete() { if (inputbuf.empty()) return false; parser_context ctx(inputbuf.c_str()); node *n; bool ro = false; std::string lasttent; int res = transform(&ctx, g_mrd, node::method, n, lasttent); if (ctx.current_column() != (int)inputbuf.size()) { node::content_type ctype; const char *cmatch; res = n->match_property(node::method, ctx.head().value.c_str(), ctype, cmatch); if (res == 1 && ctype == node::method && !strcmp(cmatch, "show")) { res = transform(&ctx, n, node::info_method, n, lasttent); ro = true; } } /* if not all buffer was consumed, we can't really complete */ if (ctx.current_column() != (int)inputbuf.size()) return false; if (res == END_LINE) { /* grunf */ if (!isspace(inputbuf[inputbuf.size()-1])) { inputbuf.resize(inputbuf.size() - lasttent.size()); inputbuf += n->name(); inputbuf += " "; } } else if (res == OK) { node::content_type ctype; const char *cmatch; res = n->match_property(node::child | (ro ? node::info_method : node::method), ctx.head().value.c_str(), ctype, cmatch); if (res == 0) { return false; } else if (res == 1) { int pos = ctx.current_column() - ctx.head().value.size(); /* if end-of-input */ if (ctx.eat() == 0) { inputbuf.resize(pos); inputbuf += cmatch; inputbuf += " "; } return true; } else { res = CONSISTENCY_ERROR; } } if (res == CONSISTENCY_ERROR) { std::string base; int count = 0; writeclient("\r\n"); for (node::properties::const_iterator i = n->get_properties().begin(); i != n->get_properties().end(); ++i) { if (i->second.is_child() || (i->second.is_method() && i->second.is_readonly() == ro)) { if (partial_match(lasttent.c_str(), i->first.c_str())) { _output.xprintf("%s ", i->first.c_str()); count++; if (base.empty()) base = i->first; else { int cn; int alen = base.size(), blen = i->first.size(); /* least common denominator */ for (cn = 0; cn < alen && cn < blen && base[cn] == i->first[cn]; cn++); if (cn < alen) base.resize(cn); } } } } if (count) { _output.newl(); if (!base.empty() && base != lasttent) { inputbuf.resize(inputbuf.size() - lasttent.size()); inputbuf += base; } } } return true; }
void telnet_console_connection::process_input(int len) { input_is_updated = false; int last = -1; int i, min_was = inputbuf.size(); int was_input = inputbuf.size(); for (i = 0; i < len; i++) { if (pmode == 0) { if ((buffer[i] == '\n' || buffer[i] == 0) && last == '\r') { if (!process_line(inputbuf.c_str())) { shutdown(); delete this; return; } inputbuf = ""; // eh.. g++ 2.95's libstdc++ doesn't have string::clear() } else if (buffer[i] == '\r') { } else if (buffer[i] == 4) { // Ctrl-D console->release_connection(this); return; } else if (buffer[i] == IAC) { pmode = 1; } else if (buffer[i] == 127 || buffer[i] == 8) { if (!inputbuf.empty()) { inputbuf.resize(inputbuf.size() - 1); if ((int)inputbuf.size() < min_was) min_was = inputbuf.size(); } } else { bool eat = false; if (authenticate_state == GotAllData) { if (buffer[i] == '\t') { if (tabcomplete()) redisplay_input(); } else if (buffer[i] == '?') { std::string wki = inputbuf; wki += '?'; writeclient("?\r\n"); dump_partial(wki.c_str()); redisplay_input(); } else if (isprint(buffer[i])) { eat = true; } else if (buffer[i] == 21) { /* Control-U */ inputbuf.clear(); clearline(); redisplay_input(); } else if (buffer[i] == 23) { /* Control-W */ int i = inputbuf.size(); for (; i > 0 && isspace(inputbuf[i-1]); i--); for (; i > 0 && !isspace(inputbuf[i-1]); i--); inputbuf.resize(i); clearline(); redisplay_input(); } else if (buffer[i] == '\033') { /* <ESC> */ /* VT100 command */ if ((len - i) >= 3) { if (buffer[i+1] == '[') { if (buffer[i+2] == 'A') { /* Up */ history_up(); } else if (buffer[i+2] == 'B') { /* Down */ history_down(); } } i += 2; } } } else { eat = true; } if (eat) inputbuf.push_back(buffer[i]); } } else if (pmode == 1) { ctlbuf.push_back(buffer[i]); if (process_cmd() && ctlbuf.empty()) pmode = 0; } last = buffer[i]; } // Ugly code ahead. if (should_echo && !input_is_updated) { std::string buf; for (i = min_was; i < was_input; i++) { buf.push_back('\b'); } int len = inputbuf.size(); if (len >= was_input) { for (i = min_was; i < len; i++) { buf.push_back(inputbuf[i]); } } else { for (i = len; i < was_input; i++) { buf.push_back(' '); } for (i = len; i < was_input; i++) { buf.push_back('\b'); } } writeclient(buf.c_str()); } }