Skip to content

Commit 1366520

Browse files
committed
Merge pull request #168 from acv/refactor-auth
Partial rewrite of fw_sync_with_auth
2 parents 98fce11 + ff90b70 commit 1366520

File tree

12 files changed

+1035
-878
lines changed

12 files changed

+1035
-878
lines changed

src/auth.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,39 @@ thread_client_timeout_check(const void *arg)
8181
}
8282
}
8383

84+
/**
85+
* @brief Logout a client and report to auth server.
86+
*
87+
* This function assumes it is being called with the client lock held! This
88+
* function remove the client from the client list and free its memory, so
89+
* client is no langer valid when this method returns.
90+
*
91+
* @param client Points to the client to be logged out
92+
*/
93+
void
94+
logout_client(t_client *client)
95+
{
96+
t_authresponse authresponse;
97+
const s_config *config = config_get_config();
98+
fw_deny(client);
99+
client_list_remove(client);
100+
101+
/* Advertise the logout if we have an auth server */
102+
if (config->auth_servers != NULL) {
103+
UNLOCK_CLIENT_LIST();
104+
auth_server_request(&authresponse, REQUEST_TYPE_LOGOUT,
105+
client->ip, client->mac, client->token,
106+
client->counters.incoming,
107+
client->counters.outgoing);
108+
109+
if (authresponse.authcode==AUTH_ERROR)
110+
debug(LOG_WARNING, "Auth server error when reporting logout");
111+
LOCK_CLIENT_LIST();
112+
}
113+
114+
client_free_node(client);
115+
}
116+
84117
/** Authenticates a single client against the central server and returns when done
85118
* Alters the firewall rules depending on what the auth server says
86119
@param r httpd request struct
@@ -162,7 +195,7 @@ authenticate_client(request *r)
162195
case AUTH_DENIED:
163196
/* Central server said invalid token */
164197
debug(LOG_INFO, "Got DENIED from central server authenticating token %s from %s at %s - deleting from firewall and redirecting them to denied message", client->token, client->ip, client->mac);
165-
fw_deny(client->ip, client->mac, FW_MARK_KNOWN);
198+
fw_deny(client);
166199
safe_asprintf(&urlFragment, "%smessage=%s",
167200
auth_server->authserv_msg_script_path_fragment,
168201
GATEWAY_MESSAGE_DENIED
@@ -176,8 +209,7 @@ authenticate_client(request *r)
176209
debug(LOG_INFO, "Got VALIDATION from central server authenticating token %s from %s at %s"
177210
"- adding to firewall and redirecting them to activate message", client->token,
178211
client->ip, client->mac);
179-
client->fw_connection_state = FW_MARK_PROBATION;
180-
fw_allow(client->ip, client->mac, FW_MARK_PROBATION);
212+
fw_allow(client, FW_MARK_PROBATION);
181213
safe_asprintf(&urlFragment, "%smessage=%s",
182214
auth_server->authserv_msg_script_path_fragment,
183215
GATEWAY_MESSAGE_ACTIVATE_ACCOUNT
@@ -190,8 +222,7 @@ authenticate_client(request *r)
190222
/* Logged in successfully as a regular account */
191223
debug(LOG_INFO, "Got ALLOWED from central server authenticating token %s from %s at %s - "
192224
"adding to firewall and redirecting them to portal", client->token, client->ip, client->mac);
193-
client->fw_connection_state = FW_MARK_KNOWN;
194-
fw_allow(client->ip, client->mac, FW_MARK_KNOWN);
225+
fw_allow(client, FW_MARK_KNOWN);
195226
served_this_session++;
196227
safe_asprintf(&urlFragment, "%sgw_id=%s",
197228
auth_server->authserv_portal_script_path_fragment,

src/auth.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#define _AUTH_H_
2929

3030
#include "httpd.h"
31+
#include "client_list.h"
3132

3233
/**
3334
* @brief Authentication codes returned by auth server.
@@ -51,6 +52,8 @@ typedef struct _t_authresponse {
5152
t_authcode authcode; /**< Authentication code returned by the server */
5253
} t_authresponse;
5354

55+
/** @brief Logout a client and report to auth server. */
56+
void logout_client(t_client *);
5457

5558
/** @brief Authenticate a single client against the central server */
5659
void authenticate_client(request *);

src/client_list.c

Lines changed: 126 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,18 @@
4444

4545
/** @internal
4646
* Holds a pointer to the first element of the list
47-
*/
48-
static t_client *firstclient = NULL;
47+
*/
48+
static t_client *firstclient = NULL;
49+
50+
/** @internal
51+
* Client ID
52+
*/
53+
static volatile unsigned long long client_id = 1;
54+
55+
/**
56+
* Mutex to protect client_id and guarantee uniqueness.
57+
*/
58+
static pthread_mutex_t client_id_mutex = PTHREAD_MUTEX_INITIALIZER;
4959

5060
/** Global mutex to protect access to the client list */
5161
pthread_mutex_t client_list_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -82,66 +92,135 @@ client_list_init(void)
8292
* @param Pointer to t_client object.
8393
*/
8494
void
85-
client_list_insert_client(t_client *client)
95+
client_list_insert_client(t_client * client)
8696
{
8797
t_client *prev_head;
8898

99+
pthread_mutex_lock(&client_id_mutex);
100+
client->id = client_id++;
101+
pthread_mutex_unlock(&client_id_mutex);
89102
prev_head = firstclient;
90103
client->next = prev_head;
91104
firstclient = client;
92105
}
93106

94-
95107
/** Based on the parameters it receives, this function creates a new entry
96108
* in the connections list. All the memory allocation is done here.
109+
* Client is inserted at the head of the list.
97110
* @param ip IP address
98111
* @param mac MAC address
99112
* @param token Token
100113
* @return Pointer to the client we just created
101114
*/
102-
t_client *
103-
client_list_append(const char *ip, const char *mac, const char *token)
115+
t_client *
116+
client_list_add(const char *ip, const char *mac, const char *token)
104117
{
105-
t_client *curclient, *prevclient;
106-
107-
prevclient = NULL;
108-
curclient = firstclient;
109-
110-
while (curclient != NULL) {
111-
prevclient = curclient;
112-
curclient = curclient->next;
113-
}
118+
t_client *curclient;
114119

115120
curclient = client_get_new();
116121

117122
curclient->ip = safe_strdup(ip);
118123
curclient->mac = safe_strdup(mac);
119124
curclient->token = safe_strdup(token);
120-
curclient->counters.incoming = curclient->counters.incoming_history = curclient->counters.outgoing = curclient->counters.outgoing_history = 0;
125+
curclient->counters.incoming = curclient->counters.incoming_history = curclient->counters.outgoing =
126+
curclient->counters.outgoing_history = 0;
121127
curclient->counters.last_updated = time(NULL);
122128

123-
if (prevclient == NULL) {
124-
firstclient = curclient;
125-
} else {
126-
prevclient->next = curclient;
127-
}
129+
client_list_insert_client(curclient);
128130

129-
debug(LOG_INFO, "Added a new client to linked list: IP: %s Token: %s",
130-
ip, token);
131+
debug(LOG_INFO, "Added a new client to linked list: IP: %s Token: %s", ip, token);
131132

132133
return curclient;
133134
}
134135

136+
/** Duplicate the whole client list to process in a thread safe way
137+
* MUTEX MUST BE HELD.
138+
* @param dest pointer TO A POINTER to a t_client (i.e.: t_client **ptr)
139+
* @return int Number of clients copied
140+
*/
141+
int
142+
client_list_dup(t_client ** dest)
143+
{
144+
t_client *new, *cur, *top, *prev;
145+
int copied = 0;
146+
147+
cur = firstclient;
148+
new = top = prev = NULL;
149+
150+
if (NULL == cur) {
151+
*dest = new; /* NULL */
152+
return copied;
153+
}
154+
155+
while (NULL != cur) {
156+
new = client_dup(cur);
157+
if (NULL == top) {
158+
/* first item */
159+
top = new;
160+
} else {
161+
prev->next = new;
162+
}
163+
prev = new;
164+
copied++;
165+
cur = cur->next;
166+
}
167+
168+
*dest = top;
169+
return copied;
170+
}
171+
172+
/** Create a duplicate of a client.
173+
* @param src Original client
174+
* @return duplicate client object with next == NULL
175+
*/
176+
t_client *
177+
client_dup(const t_client * src)
178+
{
179+
t_client *new = client_get_new();
180+
181+
new->id = src->id;
182+
new->ip = safe_strdup(src->ip);
183+
new->mac = safe_strdup(src->mac);
184+
new->token = safe_strdup(src->token);
185+
new->counters.incoming = src->counters.incoming;
186+
new->counters.incoming_history = src->counters.incoming_history;
187+
new->counters.outgoing = src->counters.outgoing;
188+
new->counters.outgoing_history = src->counters.outgoing_history;
189+
new->counters.last_updated = src->counters.last_updated;
190+
new->next = NULL;
191+
192+
return new;
193+
}
194+
195+
/** Find a client in the list from a client struct, matching operates by id.
196+
* This is useful from a copy of client to find the original.
197+
* @param client Client to find
198+
* @return pointer to the client in the list.
199+
*/
200+
t_client *
201+
client_list_find_by_client(t_client * client)
202+
{
203+
t_client *c = firstclient;
204+
205+
while (NULL != c) {
206+
if (c->id == client->id) {
207+
return c;
208+
}
209+
c = c->next;
210+
}
211+
return NULL;
212+
}
213+
135214
/** Finds a client by its IP and MAC, returns NULL if the client could not
136215
* be found
137216
* @param ip IP we are looking for in the linked list
138217
* @param mac MAC we are looking for in the linked list
139218
* @return Pointer to the client, or NULL if not found
140219
*/
141-
t_client *
220+
t_client *
142221
client_list_find(const char *ip, const char *mac)
143222
{
144-
t_client *ptr;
223+
t_client *ptr;
145224

146225
ptr = firstclient;
147226
while (NULL != ptr) {
@@ -159,10 +238,10 @@ client_list_find(const char *ip, const char *mac)
159238
* @param ip IP we are looking for in the linked list
160239
* @return Pointer to the client, or NULL if not found
161240
*/
162-
t_client *
241+
t_client *
163242
client_list_find_by_ip(const char *ip)
164243
{
165-
t_client *ptr;
244+
t_client *ptr;
166245

167246
ptr = firstclient;
168247
while (NULL != ptr) {
@@ -180,10 +259,10 @@ client_list_find_by_ip(const char *ip)
180259
* @param mac Mac we are looking for in the linked list
181260
* @return Pointer to the client, or NULL if not found
182261
*/
183-
t_client *
262+
t_client *
184263
client_list_find_by_mac(const char *mac)
185264
{
186-
t_client *ptr;
265+
t_client *ptr;
187266

188267
ptr = firstclient;
189268
while (NULL != ptr) {
@@ -202,7 +281,7 @@ client_list_find_by_mac(const char *mac)
202281
t_client *
203282
client_list_find_by_token(const char *token)
204283
{
205-
t_client *ptr;
284+
t_client *ptr;
206285

207286
ptr = firstclient;
208287
while (NULL != ptr) {
@@ -214,6 +293,22 @@ client_list_find_by_token(const char *token)
214293
return NULL;
215294
}
216295

296+
/** Destroy the client list. Including all free...
297+
* DOES NOT UPDATE firstclient or anything else.
298+
* @param list List to destroy (first item)
299+
*/
300+
void
301+
client_list_destroy(t_client * list)
302+
{
303+
t_client *next;
304+
305+
while (NULL != list) {
306+
next = list->next;
307+
client_free_node(list);
308+
list = next;
309+
}
310+
}
311+
217312
/** @internal
218313
* @brief Frees the memory used by a t_client structure
219314
* This function frees the memory used by the t_client structure in the
@@ -258,7 +353,7 @@ client_list_delete(t_client * client)
258353
void
259354
client_list_remove(t_client * client)
260355
{
261-
t_client *ptr;
356+
t_client *ptr;
262357

263358
ptr = firstclient;
264359

0 commit comments

Comments
 (0)