X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;ds=sidebyside;f=src%2FUserSession.c;fp=src%2FUserSession.c;h=136b7674b2d3d0be9ad8c9eea7d890c40c07920d;hb=4fdc419424dd18df5807ed4218a84fa38e1dd6f6;hp=0000000000000000000000000000000000000000;hpb=1f2baa2e7b90ea83c5a0c93598e22e5063fc6d95;p=TransparentIRC.git diff --git a/src/UserSession.c b/src/UserSession.c new file mode 100644 index 0000000..136b767 --- /dev/null +++ b/src/UserSession.c @@ -0,0 +1,221 @@ +/* UserSession.c - TransparentIRC 0.1 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "UserSession.h" +#include "IOHandler.h" +#include "UserClient.h" +#include "ConfigParser.h" +#include "tools.h" + +static struct UserSession *usersessions = NULL; + +static struct UserSession *usersession_add(char *username, char *password, char *nick) { + struct UserSession *session; + session = calloc(1, sizeof(*session)); + session->username = strdup(username); + session->password = strdup(password); + session->nick = strdup(nick); + + //add UserSession to the list + session->prev = NULL; + session->next = usersessions; + if(usersessions) + usersessions->prev = session; + usersessions = session; + + return session; +} + +/* +static void usersession_close(struct UserSession *session) { + if(session->client) + userclient_close(session->client); + + if(session->prev) + session->prev->next = session->next; + else + usersessions = session->next; + if(session->next) + session->next->prev = session->prev; + free(session->username); + free(session->password); + free(session->nick); + free(session); +} +*/ + +/* ****************** SESSION FUNCTIONS ****************** */ + +static void usersession_initialize_session(struct UserSession *session) { + +} + +/* ****************** EXTERNAL EVENTS ****************** */ + +void usersession_client_close(struct UserSession *session) { + session->client = NULL; + session->idle_since = time(0); + +} + +void usersession_client_notification(struct UserSession *session, char *notification) { + if(session->client) { + iohandler_printf(session->client->iofd, ":*TransparentIRC!TransIRC@TransparentIRC.system.notification NOTICE %s :[TransparentIRC] %s", session->nick, notification); + } +} + +/* ****************** LOGIN FUNCTIONS ****************** */ + +static void usersession_login_accept(struct UserLogin *login); +static void usersession_login_callback(struct IOEvent *event); + +void usersession_login(struct UserLogin *login) { + if(get_int_field("auth.external.enabled")) { + char *execute = get_string_field("auth.external.execute"); + char *parameters = get_string_field("auth.external.parameters"); + + struct variable_replace_map map[] = { + {'U', login->username}, + {'P', login->password}, + {'N', login->nick}, + {0, NULL} + }; + char paramstr[CMDLEN+1]; + build_var_string(paramstr, parameters, map); + char *argv[MAXNUMPARAMS]; + int argc = parse_line(paramstr, argv+1, 0); + argv[0] = execute; + argv[argc+1] = NULL; + int fp = run_external_process(execute, argv); + if(fp < 0) { + userclient_login_failed(login, "Login Script error."); + return; + } + struct IODescriptor *iofd = iohandler_add(fp, IOTYPE_CLIENT, usersession_login_callback); + if(iofd) { + iofd->read_lines = 1; + iofd->state = IO_CONNECTED; + int timeout = get_int_field("auth.external.timeout"); + if(timeout) { + gettimeofday(&iofd->timeout, NULL); + iofd->timeout.tv_sec += timeout; + } + iofd->data = login; + login->login_iofd = iofd; + login->client->flags |= USERCLIENT_LOGIN_PROCESSING; + } else + userclient_login_failed(login, "Internal error."); + } else + usersession_login_accept(login); +} + +static void usersession_login_accept(struct UserLogin *login) { + //search session for user (or create a new one) + struct UserSession *session, *active_session = NULL; + int sessioncount = 0; + for(session = usersessions; session; session = session->next) { + if(!stricmp(login->username, session->username)) { + sessioncount++; + if(!strcmp(login->password, session->password) && !stricmp(login->nick, session->nick)) { + active_session = session; + } + } + } + if(active_session) { + if(active_session->client) { + iohandler_printf(active_session->client->iofd, "ERROR :[TransparentIRC] Another client logged in."); + userclient_close(active_session->client); + } //active_session->client is now NULL + active_session->client = login->client; + userclient_login_successful(login, active_session, 1); + } else { + int sessionlimit = get_int_field("auth.session_limit"); + if(sessionlimit && sessioncount >= sessionlimit) { + userclient_login_failed(login, "Session limit reached."); + return; + } + active_session = usersession_add(login->username, login->password, login->nick); + if(!active_session) { + userclient_login_failed(login, "Could not create Session."); + return; + } + userclient_login_successful(login, active_session, 0); + usersession_initialize_session(active_session); + } +} + +void usersession_login_abort(struct UserLogin *login) { + struct IODescriptor *iofd = login->login_iofd; + iohandler_close(iofd); +} + +static void usersession_login_callback(struct IOEvent *event) { + struct UserLogin *login = event->iofd->data; + login->client->flags &= ~USERCLIENT_LOGIN_PROCESSING; + char *reply; + int login_finished = 0; + switch(event->type) { + case IOEVENT_RECV: + reply = event->data.recv_str; + if(!stricmplen(reply, "REJECT", 6)) { + if((reply = strchr(reply, ' '))) { + char reason[LINELEN]; + sprintf(reason, "Access denied: %s", reply + 7); + login->reject_reason = strdup(reason); + } else + login->reject_reason = strdup("Access denied."); + } else if(!stricmplen(reply, "ACCEPT", 6)) { + if((reply = strchr(reply, ' '))) { + char *passwd = strchr(reply, ' '); + if(passwd) { + *passwd = '\0'; + passwd++; + free(login->password); + login->password = strdup(passwd); + } + free(login->username); + login->username = strdup(reply); + } + login->login_accepted = 1; + } else { + char *argv[MAXNUMPARAMS]; + int argc = parse_line(reply, argv, 0); + if(argc < 2) return; + if(!stricmp(argv[0], "CLASS")) { + login->session_class = strdup(argv[1]); + } + + } + break; + case IOEVENT_TIMEOUT: + login->reject_reason = strdup("Login Script timeout."); + login_finished = 1; + break; + case IOEVENT_CLOSED: + login->reject_reason = strdup("Login Script error (no reply)."); + login_finished = 1; + break; + default: + return; + } + if(login_finished) { + iohandler_close(event->iofd); + if(login->login_accepted) + usersession_login_accept(login); + else + userclient_login_failed(login, login->reject_reason); + } +}