1 /* UserSession.c - TransparentIRC 0.1
2 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "UserSession.h"
18 #include "IOHandler.h"
19 #include "UserClient.h"
20 #include "ConfigParser.h"
23 static struct UserSession *usersessions = NULL;
25 static struct UserSession *usersession_add(char *username, char *password, char *nick) {
26 struct UserSession *session;
27 session = calloc(1, sizeof(*session));
28 session->username = strdup(username);
29 session->password = strdup(password);
30 session->nick = strdup(nick);
32 //add UserSession to the list
34 session->next = usersessions;
36 usersessions->prev = session;
37 usersessions = session;
43 static void usersession_close(struct UserSession *session) {
45 userclient_close(session->client);
48 session->prev->next = session->next;
50 usersessions = session->next;
52 session->next->prev = session->prev;
53 free(session->username);
54 free(session->password);
60 /* ****************** SESSION FUNCTIONS ****************** */
62 static void usersession_initialize_session(struct UserSession *session) {
66 /* ****************** EXTERNAL EVENTS ****************** */
68 void usersession_client_close(struct UserSession *session) {
69 session->client = NULL;
70 session->idle_since = time(0);
74 void usersession_client_notification(struct UserSession *session, char *notification) {
76 iohandler_printf(session->client->iofd, ":*TransparentIRC!TransIRC@TransparentIRC.system.notification NOTICE %s :[TransparentIRC] %s", session->nick, notification);
80 /* ****************** LOGIN FUNCTIONS ****************** */
82 static void usersession_login_accept(struct UserLogin *login);
83 static void usersession_login_callback(struct IOEvent *event);
85 void usersession_login(struct UserLogin *login) {
86 if(get_int_field("auth.external.enabled")) {
87 char *execute = get_string_field("auth.external.execute");
88 char *parameters = get_string_field("auth.external.parameters");
90 struct variable_replace_map map[] = {
91 {'U', login->username},
92 {'P', login->password},
96 char paramstr[CMDLEN+1];
97 build_var_string(paramstr, parameters, map);
98 char *argv[MAXNUMPARAMS];
99 int argc = parse_line(paramstr, argv+1, 0);
102 int fp = run_external_process(execute, argv);
104 userclient_login_failed(login, "Login Script error.");
107 struct IODescriptor *iofd = iohandler_add(fp, IOTYPE_CLIENT, usersession_login_callback);
109 iofd->read_lines = 1;
110 iofd->state = IO_CONNECTED;
111 int timeout = get_int_field("auth.external.timeout");
113 gettimeofday(&iofd->timeout, NULL);
114 iofd->timeout.tv_sec += timeout;
117 login->login_iofd = iofd;
118 login->client->flags |= USERCLIENT_LOGIN_PROCESSING;
120 userclient_login_failed(login, "Internal error.");
122 usersession_login_accept(login);
125 static void usersession_login_accept(struct UserLogin *login) {
126 //search session for user (or create a new one)
127 struct UserSession *session, *active_session = NULL;
128 int sessioncount = 0;
129 for(session = usersessions; session; session = session->next) {
130 if(!stricmp(login->username, session->username)) {
132 if(!strcmp(login->password, session->password) && !stricmp(login->nick, session->nick)) {
133 active_session = session;
138 if(active_session->client) {
139 iohandler_printf(active_session->client->iofd, "ERROR :[TransparentIRC] Another client logged in.");
140 userclient_close(active_session->client);
141 } //active_session->client is now NULL
142 active_session->client = login->client;
143 userclient_login_successful(login, active_session, 1);
145 int sessionlimit = get_int_field("auth.session_limit");
146 if(sessionlimit && sessioncount >= sessionlimit) {
147 userclient_login_failed(login, "Session limit reached.");
150 active_session = usersession_add(login->username, login->password, login->nick);
151 if(!active_session) {
152 userclient_login_failed(login, "Could not create Session.");
155 userclient_login_successful(login, active_session, 0);
156 usersession_initialize_session(active_session);
160 void usersession_login_abort(struct UserLogin *login) {
161 struct IODescriptor *iofd = login->login_iofd;
162 iohandler_close(iofd);
165 static void usersession_login_callback(struct IOEvent *event) {
166 struct UserLogin *login = event->iofd->data;
167 login->client->flags &= ~USERCLIENT_LOGIN_PROCESSING;
169 int login_finished = 0;
170 switch(event->type) {
172 reply = event->data.recv_str;
173 if(!stricmplen(reply, "REJECT", 6)) {
174 if((reply = strchr(reply, ' '))) {
175 char reason[LINELEN];
176 sprintf(reason, "Access denied: %s", reply + 7);
177 login->reject_reason = strdup(reason);
179 login->reject_reason = strdup("Access denied.");
180 } else if(!stricmplen(reply, "ACCEPT", 6)) {
181 if((reply = strchr(reply, ' '))) {
182 char *passwd = strchr(reply, ' ');
186 free(login->password);
187 login->password = strdup(passwd);
189 free(login->username);
190 login->username = strdup(reply);
192 login->login_accepted = 1;
194 char *argv[MAXNUMPARAMS];
195 int argc = parse_line(reply, argv, 0);
197 if(!stricmp(argv[0], "CLASS")) {
198 login->session_class = strdup(argv[1]);
203 case IOEVENT_TIMEOUT:
204 login->reject_reason = strdup("Login Script timeout.");
208 login->reject_reason = strdup("Login Script error (no reply).");
215 iohandler_close(event->iofd);
216 if(login->login_accepted)
217 usersession_login_accept(login);
219 userclient_login_failed(login, login->reject_reason);