channel_t *ch, *ch_itr = NULL;
ch = Chan_createChannel(chdesc.name, chdesc.description);
ch->noenter = chdesc.noenter;
-
+ if (chdesc.password)
+ ch->password = strdup(chdesc.password);
if (strcmp(defaultChannelName, chdesc.name) == 0) {
Log_info("Setting default channel %s", ch->name);
defaultChan = ch;
if (defaultChan->noenter)
Log_fatal("Error in channel configuration: default channel is marked as noenter");
+ if (defaultChan->password)
+ Log_fatal("Error in channel configuration: default channel has a password");
/* Channel links */
for (i = 0; ; i++) {
free(ch->name);
if (ch->desc)
free(ch->desc);
+ if (ch->password)
+ free(ch->password);
free(ch);
}
}
return Chan_userJoin(ch_itr, client);
}
-bool_t Chan_userJoin_id_test(int channelid)
+channelJoinResult_t Chan_userJoin_id_test(int channelid, client_t *client)
{
channel_t *ch_itr = NULL;
do {
} while (ch_itr != NULL && ch_itr->id != channelid);
if (ch_itr == NULL) {
Log_warn("Channel id %d not found - ignoring.", channelid);
- return false;
+ return CHJOIN_NOTFOUND;
}
- if (ch_itr->noenter)
- return false;
- else
- return true;
+ else if (ch_itr->noenter)
+ return CHJOIN_NOENTER;
+ else if (ch_itr->password && !Client_token_match(client, ch_itr->password))
+ return CHJOIN_WRONGPW;
+ else return CHJOIN_OK;
}
#if 0
int id;
char *name;
char *desc;
+ char *password;
struct channel *parent;
bool_t temporary, noenter;
struct dlist node;
struct dlist node;
} channellist_t;
+typedef enum {
+ CHJOIN_OK,
+ CHJOIN_NOENTER,
+ CHJOIN_WRONGPW,
+ CHJOIN_NOTFOUND,
+} channelJoinResult_t;
+
void Chan_init();
void Chan_free();
void Chan_addChannel(channel_t *parent, channel_t *sub);
int Chan_userJoin(channel_t *ch, client_t *client);
int Chan_userJoin_id(int channelid, client_t *client);
int Chan_userLeave(client_t *client);
-bool_t Chan_userJoin_id_test(int channelid);
+channelJoinResult_t Chan_userJoin_id_test(int channelid, client_t *client);
channel_t *Chan_iterate(channel_t **channelpptr);
channel_t *Chan_iterate_siblings(channel_t *parent, channel_t **channelpptr);
channel_t *Chan_createChannel(const char *name, const char *desc);
return cd;
}
+void Client_token_add(client_t *client, char *token_string)
+{
+ token_t *token;
+
+ if (client->tokencount >= MAX_TOKENS)
+ return;
+ token = malloc(sizeof(token_t));
+ if (token == NULL)
+ Log_fatal("Out of memory");
+ init_list_entry(&token->node);
+ token->token = strdup(token_string);
+ if (token->token == NULL)
+ Log_fatal("Out of memory");
+ list_add_tail(&token->node, &client->tokens);
+ client->tokencount++;
+}
+
+bool_t Client_token_match(client_t *client, char *str)
+{
+ token_t *token;
+ struct dlist *itr;
+
+ if (list_empty(&client->tokens))
+ return false;
+ list_iterate(itr, &client->tokens) {
+ token = list_get_entry(itr, token_t, node);
+ if (strncasecmp(token->token, str, MAX_TOKENSIZE) == 0)
+ return true;
+ }
+ return false;
+}
+
+void Client_token_free(client_t *client)
+{
+ struct dlist *itr, *save;
+ token_t *token;
+
+ list_iterate_safe(itr, save, &client->tokens) {
+ token = list_get_entry(itr, token_t, node);
+ list_del(&token->node);
+ free(token->token);
+ free(token);
+ }
+ client->tokencount = 0;
+}
+
void recheckCodecVersions()
{
client_t *client_itr = NULL;
init_list_entry(&newclient->node);
init_list_entry(&newclient->voicetargets);
init_list_entry(&newclient->codecs);
+ init_list_entry(&newclient->tokens);
list_add_tail(&newclient->node, &clients);
clientcount++;
}
Client_codec_free(client);
Voicetarget_free_all(client);
+ Client_token_free(client);
list_del(&client->node);
if (client->ssl)
#define UDP_BUFSIZE 512
#define INACTICITY_TIMEOUT 15 /* Seconds */
#define MAX_CODECS 10
+#define MAX_TOKENSIZE 64
+#define MAX_TOKENS 32
#define IS_AUTH(_a_) ((_a_)->authenticated)
char *context;
struct dlist chan_node;
struct dlist voicetargets;
+ struct dlist tokens;
+ int tokencount;
float UDPPingAvg, UDPPingVar, TCPPingAvg, TCPPingVar;
uint32_t UDPPackets, TCPPackets;
} client_t;
struct dlist node;
} codec_t;
+typedef struct {
+ char *token;
+ struct dlist node;
+} token_t;
+
void Client_init();
int Client_getfds(struct pollfd *pollfds);
void Client_janitor();
Client_send_message(client, msg);
}
+static void addTokens(client_t *client, message_t *msg)
+{
+ int i;
+ if (client->tokencount + msg->payload.authenticate->n_tokens < MAX_TOKENS) {
+ /* Check lengths first */
+ for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
+ if (strlen(msg->payload.authenticate->tokens[i]) > MAX_TOKENSIZE - 1) {
+ sendPermissionDenied(client, "Too long token");
+ return;
+ }
+ }
+
+ for (i = 0; i < msg->payload.authenticate->n_tokens; i++) {
+ Log_debug("Adding token '%s' to client '%s'", msg->payload.authenticate->tokens[i], client->username);
+ Client_token_add(client, msg->payload.authenticate->tokens[i]);
+ }
+ }
+ else
+ sendPermissionDenied(client, "Too many tokens");
+}
+
void Mh_handle_message(client_t *client, message_t *msg)
{
message_t *sendmsg = NULL;
Log_debug("Authenticate message received");
if (IS_AUTH(client) || !msg->payload.authenticate->username) {
- /* Authenticate message might be sent when a token is set by the user.*/
+ /* Authenticate message might be sent when a tokens are changed by the user.*/
+ Client_token_free(client); /* Clear the token list */
if (msg->payload.authenticate->n_tokens > 0) {
- Log_debug("Tokens in auth message from %s", client->username);
+ Log_debug("Tokens in auth message from '%s'. n_tokens = %d", client->username,
+ msg->payload.authenticate->n_tokens);
+ addTokens(client, msg);
}
break;
}
goto disconnect;
}
- /* Name & password */
+ /* Name */
client->username = strdup(msg->payload.authenticate->username);
+
+ /* Tokens */
+ if (msg->payload.authenticate->n_tokens > 0)
+ addTokens(client, msg);
+
/* Setup UDP encryption */
CryptState_init(&client->cryptState);
}
if (msg->payload.userState->has_channel_id) {
int leave_id;
- if (!Chan_userJoin_id_test(msg->payload.userState->channel_id))
+ channelJoinResult_t chjoin_rc = Chan_userJoin_id_test(msg->payload.userState->channel_id, client);
+
+ if (chjoin_rc != CHJOIN_OK) {
+ if (chjoin_rc == CHJOIN_WRONGPW) {
+ sendPermissionDenied(client, "Wrong channel password");
+ }
break;
+ }
+
leave_id = Chan_userJoin_id(msg->payload.userState->channel_id, client);
if (leave_id > 0) {
Log_debug("Removing channel ID %d", leave_id);