예제 #1
0
void telnet_console_connection::redisplay_input() {
	writeclient("\r");
	writeclient(prompt.c_str());
	writeclient(inputbuf.c_str());

	input_is_updated = true;
}
예제 #2
0
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;
}
예제 #3
0
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);
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
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;
}
예제 #7
0
void telnet_console_connection::flushed(const char *str, bool newline) {
	writeclient(str);
	if (newline)
		writeclient("\r\n");
}
예제 #8
0
void telnet_console_connection::show_prompt() {
	clearline();
	writeclient(prompt.c_str());
}
예제 #9
0
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;
}
예제 #10
0
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());
	}
}