void Ban_deinit(void)
{
- /* Save banlist */
+ /* Save banlist */
if (getStrConf(BANFILE) != NULL)
Ban_saveBanFile();
-
+
Ban_clearBanList();
}
if (ban == NULL)
Log_fatal("Out of memory");
memset(ban, 0, sizeof(ban_t));
-
+
memcpy(ban->hash, client->hash, 20);
memcpy(&ban->address, &client->remote_tcp.sin_addr, sizeof(in_addr_t));
ban->mask = 128;
banlist_changed = true;
if(getBoolConf(SYNC_BANFILE))
Ban_saveBanFile();
-
+
SSLi_hash2hex(ban->hash, hexhash);
Log_info_client(client, "User kickbanned. Reason: '%s' Hash: %s IP: %s Banned for: %d seconds",
ban->reason, hexhash, inet_ntoa(*((struct in_addr *)&ban->address)), ban->duration);
ban_t *ban;
char hexhash[41];
uint64_t bantime_long;
-
+
list_iterate(itr, &banlist) {
ban = list_get_entry(itr, ban_t, node);
bantime_long = ban->duration * 1000000LL;
ban_t *ban;
list_iterate(itr, &banlist) {
ban = list_get_entry(itr, ban_t, node);
- if (memcmp(ban->hash, client->hash, 20) == 0)
+ if (memcmp(ban->hash, client->hash, 20) == 0)
return true;
}
return false;
-
+
}
bool_t Ban_isBannedAddr(in_addr_t *addr)
ban_t *ban;
int mask;
in_addr_t tempaddr1, tempaddr2;
-
+
list_iterate(itr, &banlist) {
ban = list_get_entry(itr, ban_t, node);
mask = ban->mask - 96;
tempaddr1 &= (2 ^ mask) - 1;
tempaddr2 &= (2 ^ mask) - 1;
}
- if (memcmp(&tempaddr1, &tempaddr2, sizeof(in_addr_t)) == 0)
+ if (memcmp(&tempaddr1, &tempaddr2, sizeof(in_addr_t)) == 0)
return true;
}
return false;
char timestr[32];
char hexhash[41];
uint8_t address[16];
-
+
msg = Msg_banList_create(bancount);
list_iterate(itr, &banlist) {
ban = list_get_entry(itr, ban_t, node);
char *hexhash, *name, *reason, *start;
uint32_t duration, mask;
uint8_t *address;
-
+
for (i = 0; i < n_bans; i++) {
Msg_banList_getEntry(msg, i, &address, &mask, &name, &hexhash, &reason, &start, &duration);
ban = malloc(sizeof(ban_t));
p = strtok(NULL, "\n");
if (p == NULL) break;
reason = p;
-
+
ban = malloc(sizeof(ban_t));
if (ban == NULL)
Log_fatal("Out of memory");
if (list_get_next(&ch->node) == &list_get_entry(&ch->node, channel_t, node)->parent->subs)
return NULL;
else
- return list_get_entry(list_get_next(&ch->node), channel_t, node);
+ return list_get_entry(list_get_next(&ch->node), channel_t, node);
}
#endif
*channelpptr = ch;
return ch;
}
-
+
void Chan_init()
{
int i;
const char *defaultChannelName;
defaultChannelName = getStrConf(DEFAULT_CHANNEL);
-
+
for (i = 0; ; i++) {
if (Conf_getNextChannel(&chdesc, i) < 0) {
if (i == 0)
ch->position = chdesc.position;
ch->silent = chdesc.silent;
if (chdesc.password) {
- Log_info("Setting password on channel '%s'", ch->name);
+ Log_info("Setting password on channel '%s'", ch->name);
ch->password = strdup(chdesc.password);
}
if (strcmp(defaultChannelName, chdesc.name) == 0) {
- Log_info("Setting default channel '%s'", ch->name);
+ Log_info("Setting default channel '%s'", ch->name);
defaultChan = ch;
}
-
+
do {
Chan_iterate(&ch_itr);
} while (ch_itr != NULL && strcmp(ch_itr->name, chdesc.parent) != 0);
-
+
if (ch_itr == NULL)
Log_fatal("Error in channel configuration: parent '%s' not found", chdesc.parent);
else {
}
if (defaultChan == NULL)
defaultChan = rootChan;
-
+
if (defaultChan->noenter)
Log_fatal("Error in channel configuration: default channel is marked as noenter");
if (defaultChan->password)
chlink.source);
else
ch_src = ch_itr;
-
- ch_itr = NULL;
+
+ ch_itr = NULL;
do {
Chan_iterate(&ch_itr);
} while (ch_itr != NULL && strcmp(ch_itr->name, chlink.destination) != 0);
chlink.destination);
else
ch_dst = ch_itr;
-
+
list_add_tail(&ch_dst->link_node, &ch_src->channel_links);
ch_src->linkcount++;
Log_info("Adding channel link '%s' -> '%s'", ch_src->name, ch_dst->name);
{
struct dlist *itr, *save;
channel_t *ch;
-
+
list_iterate_safe(itr, save, &channels) {
ch = list_get_entry(itr, channel_t, flatlist_node);
Log_debug("Free channel '%s'", ch->name);
{
channel_t *leaving = NULL;
int leaving_id = -1;
-
+
if (client->channel) {
list_del(&client->chan_node);
leaving = (channel_t *)client->channel;
/* Do nothing if user already is in this channel */
if ((channel_t *)client->channel == ch)
return 0;
-
- Log_debug("Add user %s to channel %s", client->username, ch->name);
+
+ Log_debug("Add user %s to channel %s", client->username, ch->name);
/* Only allowed in one channel at a time */
leaving_id = Chan_userLeave(client);
list_add_tail(&client->chan_node, &ch->clients);
return -1;
}
else
- return Chan_userJoin(ch_itr, client);
+ return Chan_userJoin(ch_itr, client);
}
channelJoinResult_t Chan_userJoin_id_test(int channelid, client_t *client)
channellist_t *chl;
struct dlist *itr;
channel_t *sub;
-
+
chl = malloc(sizeof(channellist_t));
chl->chan = ch;
init_list_entry(&chl->node);
c->availableBandwidth += maxBandwidth;
if (c->availableBandwidth > bwTop)
c->availableBandwidth = bwTop;
-
+
if (Timer_isElapsed(&c->lastActivity, 1000000LL * INACTIVITY_TIMEOUT)) {
/* No activity from client - assume it is lost and close. */
Log_info_client(c, "Timeout, closing.");
if (list_empty(&client->codecs))
return NULL;
-
+
if (cd == NULL) {
cd = list_get_entry(list_get_first(&client->codecs), codec_t, node);
} else {
{
token_t *token;
struct dlist *itr;
-
+
if (list_empty(&client->tokens))
return false;
list_iterate(itr, &client->tokens) {
{
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);
bool_t enableOpus;
init_list_entry(&codec_list);
-
+
while (Client_iterate(&client_itr) != NULL) {
codec_itr = NULL;
if (client_itr->codec_count == 0 && !client_itr->bOpus)
continue;
while (Client_codec_iterate(client_itr, &codec_itr) != NULL) {
- found = false;
+ found = false;
list_iterate(itr, &codec_list) {
cd = list_get_entry(itr, codec_t, node);
if (cd->codec == codec_itr->codec) {
if (client_itr->bOpus)
opus++;
}
- if (users == 0)
+ if (users == 0)
return;
enableOpus = ((opus * 100 / users) >= getIntConf(OPUS_THRESHOLD));
bPreferAlpha = true;
else
bPreferAlpha = !bPreferAlpha;
-
+
if (bPreferAlpha)
iCodecAlpha = version;
else
sendmsg->payload.codecVersion->opus = enableOpus;
Client_send_message_except(NULL, sendmsg);
-
+
if (enableOpus && !bOpus) {
client_itr = NULL;
while (Client_iterate(&client_itr) != NULL) {
Client_textmessage(client_itr, OPUS_WARN_SWITCHING);
}
}
- Log_info("OPUS codec %s", bOpus ? "enabled" : "disabled");
+ Log_info("OPUS codec %s", bOpus ? "enabled" : "disabled");
}
-
+
bOpus = enableOpus;
}
newclient->sessionId = findFreeSessionId();
if (newclient->sessionId < 0)
Log_fatal("Could not find a free session ID");
-
+
init_list_entry(&newclient->txMsgQueue);
init_list_entry(&newclient->chan_node);
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++;
-
+
/* Send version message to client */
sendmsg = Msg_create(Version);
sendmsg->payload.version->has_version = true;
Client_codec_free(client);
Voicetarget_free_all(client);
Client_token_free(client);
-
+
list_del(&client->node);
if (client->ssl)
SSLi_free(client->ssl);
if (client->release)
free(client->release);
if (client->os)
- free(client->os);
+ free(client->os);
if (client->os_version)
- free(client->os_version);
+ free(client->os_version);
if (client->username)
free(client->username);
if (client->context)
void Client_disconnect_all()
{
struct dlist *itr, *save;
-
+
list_iterate_safe(itr, save, &clients) {
Client_free(list_get_entry(itr, client_t, node));
}
{
struct dlist *itr;
client_t *client = NULL;
-
+
list_iterate(itr, &clients) {
if (fd == list_get_entry(itr, client_t, node)->tcpfd) {
client = list_get_entry(itr, client_t, node);
int rc;
Timer_restart(&client->lastActivity);
-
+
if (client->writeBlockedOnRead) {
client->writeBlockedOnRead = false;
Log_debug("Client_read: writeBlockedOnRead == true");
return Client_write(client);
}
-
+
if (client->shutdown_wait) {
Client_free(client);
return 0;
do {
errno = 0;
- if (!client->msgsize)
+ if (!client->msgsize)
rc = SSLi_read(client->ssl, &client->rxbuf[client->rxcount], 6 - client->rxcount);
else
rc = SSLi_read(client->ssl, &client->rxbuf[client->rxcount], client->msgsize);
client->readBlockedOnWrite = true;
return 0;
}
- else if (SSLi_get_error(client->ssl, rc) == SSLI_ERROR_ZERO_RETURN ||
+ else if (SSLi_get_error(client->ssl, rc) == SSLI_ERROR_ZERO_RETURN ||
SSLi_get_error(client->ssl, rc) == 0) {
Log_info_client(client, "Connection closed by peer");
Client_close(client);
if (errno == 0)
Log_info_client(client, "Connection closed by peer");
else
- Log_info_client(client,"Error: %s - Closing connection (code %d)",
+ Log_info_client(client,"Error: %s - Closing connection (code %d)",
strerror(errno));
}
else if (SSLi_get_error(client->ssl, rc) == SSLI_ERROR_CONNRESET) {
}
}
} while (SSLi_data_pending(client->ssl));
-
+
return 0;
}
{
struct dlist *itr;
client_t *client = NULL;
-
+
list_iterate(itr, &clients) {
if(fd == list_get_entry(itr, client_t, node)->tcpfd) {
client = list_get_entry(itr, client_t, node);
int Client_write(client_t *client)
{
int rc;
-
+
if (client->readBlockedOnWrite) {
client->readBlockedOnWrite = false;
Log_debug("Client_write: readBlockedOnWrite == true");
if (list_empty(&clients))
return NULL;
-
+
if (c == NULL) {
c = list_get_entry(list_get_first(&clients), client_t, node);
} else {
{
client_t *itr = NULL;
int count = 0;
-
+
Msg_inc_ref(msg); /* Make sure a reference is held during the whole iteration. */
while (Client_iterate(&itr) != NULL) {
if (itr != client) {
}
}
Msg_free(msg); /* Free our reference to the message */
-
+
if (count == 0)
Msg_free(msg); /* If only 1 client is connected then no message is passed
* to Client_send_message(). Free it here. */
-
+
return 0;
}
{
client_t *itr = NULL;
int count = 0;
-
+
Msg_inc_ref(msg); /* Make sure a reference is held during the whole iteration. */
while (Client_iterate(&itr) != NULL) {
if (itr != client) {
}
}
Msg_free(msg); /* Free our reference to the message */
-
+
if (count == 0)
Msg_free(msg); /* If only 1 client is connected then no message is passed
* to Client_send_message(). Free it here. */
-
+
return 0;
}
if (Timer_elapsed(&client->cryptState.tLastRequest) > 5000000ULL) {
message_t *sendmsg;
Timer_restart(&client->cryptState.tLastRequest);
-
+
sendmsg = Msg_create(CryptSetup);
- Log_info_client(client, "Requesting voice channel crypt resync");
+ Log_info_client(client, "Requesting voice channel crypt resync");
Client_send_message(client, sendmsg);
}
}
uint64_t key;
client_t *itr;
UDPMessageType_t msgType;
-
+
#if defined(__LP64__)
uint8_t encbuff[UDP_PACKET_SIZE + 8];
uint8_t *encrypted = encbuff + 4;
uint8_t encrypted[UDP_PACKET_SIZE];
#endif
uint8_t buffer[UDP_PACKET_SIZE];
-
+
len = recvfrom(udpsock, encrypted, UDP_PACKET_SIZE, MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
if (len == 0) {
return -1;
ping[3] = htonl((uint32_t)clientcount);
ping[4] = htonl((uint32_t)getIntConf(MAX_CLIENTS));
ping[5] = htonl((uint32_t)getIntConf(MAX_BANDWIDTH));
-
+
sendto(udpsock, encrypted, 6 * sizeof(uint32_t), 0, (struct sockaddr *)&from, fromlen);
return 0;
}
-
+
key = (((uint64_t)from.sin_addr.s_addr) << 16) ^ from.sin_port;
itr = NULL;
-
+
while (Client_iterate(&itr) != NULL) {
if (itr->key == key) {
if (!checkDecrypt(itr, encrypted, buffer, len))
goto out;
break;
}
- }
+ }
if (itr == NULL) { /* Unknown peer */
while (Client_iterate(&itr) != NULL) {
if (itr->remote_tcp.sin_addr.s_addr == from.sin_addr.s_addr) {
if (itr == NULL) { /* Couldn't find this peer among connected clients */
goto out;
}
-
+
itr->bUDP = true;
len -= 4; /* Adjust for crypt header */
msgType = (UDPMessageType_t)((buffer[0] >> 5) & 0x7);
Log_debug("Unknown UDP message type from %s port %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
break;
}
-
+
out:
return 0;
}
src->context != NULL && dst->context != NULL && /* ...both source and destination has context */
strcmp(src->context, dst->context) == 0) /* ...and the contexts match */
Client_send_udp(dst, data, len);
- else
+ else
Client_send_udp(dst, data, len - poslen);
}
}
unsigned int poslen, counter, size;
int offset, packetsize;
voicetarget_t *vt;
-
+
channel_t *ch = (channel_t *)client->channel;
struct dlist *itr;
-
+
if (!client->authenticated || client->mute || client->self_mute || ch->silent)
goto out;
-
+
packetsize = 20 + 8 + 4 + len;
if (client->availableBandwidth - packetsize < 0)
goto out; /* Discard */
client->availableBandwidth -= packetsize;
-
+
Timer_restart(&client->idleTime);
Timer_restart(&client->lastActivity);
-
+
counter = Pds_get_numval(pdi); /* step past session id */
if ((type >> 5) != UDPVoiceOpus) {
do {
size = Pds_get_numval(pdi);
Pds_skip(pdi, size & 0x1fff);
}
-
+
poslen = pdi->maxsize - pdi->offset; /* For stripping of positional info */
-
+
Pds_add_numval(pds, client->sessionId);
Pds_append_data_nosize(pds, data + 1, len - 1);
-
+
if (target == 0x1f) { /* Loopback */
buffer[0] = (uint8_t) type;
Client_send_udp(client, buffer, pds->offset + 1);
}
else if (target == 0) { /* regular channel speech */
buffer[0] = (uint8_t) type;
-
+
if (ch == NULL)
goto out;
-
+
list_iterate(itr, &ch->clients) {
client_t *c;
c = list_get_entry(itr, client_t, chan_node);
}
Chan_freeTreeList(&chanlist);
}
- }
+ }
/* Sessions */
for (i = 0; i < TARGET_MAX_SESSIONS && vt->sessions[i] != -1; i++) {
client_t *c;
out:
Pds_free(pds);
Pds_free(pdi);
-
+
return 0;
}
#endif
if (mbuf == NULL)
Log_fatal("Out of memory");
-
+
CryptState_encrypt(&client->cryptState, data, buf, len);
-
+
sendto(udpsock, buf, len + 4, 0, (struct sockaddr *)&client->remote_udp, sizeof(struct sockaddr_in));
-
+
free(mbuf);
} else {
message_t *msg;
{
config_setting_t *setting = NULL;
const char *strsetting = NULL;
-
+
switch (param) {
case CERTIFICATE:
setting = config_lookup(&configuration, "certificate");
int getIntConf(param_t param)
{
config_setting_t *setting = NULL;
-
+
switch (param) {
case BINDPORT:
setting = config_lookup(&configuration, "bindport");
bool_t getBoolConf(param_t param)
{
config_setting_t *setting = NULL;
-
+
switch (param) {
case ALLOW_TEXTMESSAGE:
setting = config_lookup(&configuration, "allow_textmessage");
config_setting_t *setting = NULL;
int maxconfig = 64, ret = 0;
char configstr[maxconfig];
-
+
ret = snprintf(configstr, maxconfig, "channels.[%d].name", index);
setting = config_lookup(&configuration, configstr);
if (ret >= maxconfig || ret < 0 || setting == NULL)
return -1; /* Required */
chdesc->name = config_setting_get_string(setting);
-
+
ret = snprintf(configstr, maxconfig, "channels.[%d].parent", index);
setting = config_lookup(&configuration, configstr);
if (ret >= maxconfig || ret < 0 || setting == NULL)
return -1; /* Required */
chdesc->parent = config_setting_get_string(setting);
-
+
ret = snprintf(configstr, maxconfig, "channels.[%d].description", index);
setting = config_lookup(&configuration, configstr);
if (ret >= maxconfig || ret < 0 || setting == NULL) /* Optional */
chdesc->description = NULL;
else
chdesc->description = config_setting_get_string(setting);
-
+
ret = snprintf(configstr, maxconfig, "channels.[%d].password", index);
setting = config_lookup(&configuration, configstr);
if (ret >= maxconfig || ret < 0 || setting == NULL) /* Optional */
chdesc->password = NULL;
else
chdesc->password = config_setting_get_string(setting);
-
+
ret = snprintf(configstr, maxconfig, "channels.[%d].noenter", index);
setting = config_lookup(&configuration, configstr);
if (ret >= maxconfig || ret < 0 || setting == NULL) /* Optional */
chdesc->noenter = false;
else
chdesc->noenter = config_setting_get_bool(setting);
-
+
ret = snprintf(configstr, maxconfig, "channels.[%d].silent", index);
setting = config_lookup(&configuration, configstr);
if (ret >= maxconfig || ret < 0 || setting == NULL) /* Optional */
chdesc->silent = false;
else
chdesc->silent = config_setting_get_bool(setting);
-
+
ret = snprintf(configstr, maxconfig, "channels.[%d].position", index);
setting = config_lookup(&configuration, configstr);
if (ret >= maxconfig || ret < 0 || setting == NULL) /* Optional */
config_setting_t *setting = NULL;
int maxconfig = 64, ret = 0;
char configstr[maxconfig];
-
+
ret = snprintf(configstr, maxconfig, "channel_links.[%d].source", index);
setting = config_lookup(&configuration, configstr);
if (ret >= maxconfig || ret < 0 || setting == NULL)
CryptState_ocb_decrypt(cs, source+4, dst, plain_length, cs->decrypt_iv, tag);
if (memcmp(tag, source+1, 3) != 0) {
- memcpy(cs->decrypt_iv, saveiv, AES_BLOCK_SIZE);
+ memcpy(cs->decrypt_iv, saveiv, AES_BLOCK_SIZE);
return false;
}
cs->decrypt_history[cs->decrypt_iv[0]] = cs->decrypt_iv[1];
/* Set the stream as line buffered */
if (setvbuf(logfile, NULL, _IOLBF, 0) < 0)
Log_fatal("setvbuf() failed: %s\n", strerror(errno));
-
+
/* XXX - Is it neccessary/appropriate that logging to file is non-blocking?
* If not, there's a risk that execution blocks, meaning that voice blocks
* as well since uMurmur is single threaded by design. OTOH, what could
void Log_init(bool_t terminal)
{
const char *logfilename;
-
- termprint = terminal;
+
+ termprint = terminal;
if (termprint)
return;
-
+
logfilename = getStrConf(LOGFILE);
if (logfilename != NULL) {
openlogfile(logfilename);
return;
else if (logfile)
fclose(logfile);
- else
+ else
closelog();
}
-
+
void Log_reset()
{
const char *logfilename;
-
+
if (logfile) {
logfilename = getStrConf(LOGFILE);
fclose(logfile);
{
va_list argp;
char buf[STRSIZE + 1];
-
+
va_start(argp, logstring);
vsnprintf(&buf[0], STRSIZE, logstring, argp);
va_end(argp);
-
+
if (termprint)
fprintf(stderr, "%s\n", buf);
else if (logfile)
va_list argp;
char buf[STRSIZE + 1];
int offset = 0;
-
+
if (termprint || logfile)
offset = sprintf(buf, "WARN: ");
-
+
va_start(argp, logstring);
vsnprintf(&buf[offset], STRSIZE - offset, logstring, argp);
va_end(argp);
-
+
if (termprint)
fprintf(stderr, "%s\n", buf);
else if (logfile)
va_list argp;
char buf[STRSIZE + 1];
int offset = 0;
-
+
if (termprint || logfile)
offset = sprintf(buf, "INFO: ");
-
- va_start(argp, logstring);
+
+ va_start(argp, logstring);
vsnprintf(&buf[offset], STRSIZE - offset, logstring, argp);
va_end(argp);
-
+
if (termprint)
fprintf(stderr, "%s\n", buf);
else if (logfile)
va_list argp;
char buf[STRSIZE + 1];
int offset = 0;
-
+
if (termprint || logfile)
offset = sprintf(buf, "INFO: ");
va_start(argp, logstring);
offset += vsnprintf(&buf[offset], STRSIZE - offset, logstring, argp);
va_end(argp);
-
+
offset += snprintf(&buf[offset], STRSIZE - offset, " - [%d] %s@%s:%d",
client->sessionId,
client->username == NULL ? "" : client->username,
va_list argp;
char buf[STRSIZE + 1];
int offset = 0;
-
+
if (termprint || logfile)
offset = sprintf(buf, "DEBUG: ");
-
- va_start(argp, logstring);
+
+ va_start(argp, logstring);
vsnprintf(&buf[offset], STRSIZE - offset, logstring, argp);
va_end(argp);
if (termprint)
va_list argp;
char buf[STRSIZE + 1];
int offset = 0;
-
+
if (termprint || logfile)
offset = sprintf(buf, "FATAL: ");
-
- va_start(argp, logstring);
+
+ va_start(argp, logstring);
vsnprintf(&buf[offset], STRSIZE - offset, logstring, argp);
va_end(argp);
-
+
if (termprint)
fprintf(stderr, "%s\n", buf);
else if (logfile)
fprintf(logfile, "%s %s\n", timestring(), buf);
else { /* If logging subsystem is not initialized, fall back to stderr +
- * syslog logging for fatal errors.
+ * syslog logging for fatal errors.
*/
if (!init) {
openlog("uMurmurd", LOG_PID, LOG_DAEMON);
}
syslog(LOG_CRIT, "%s", buf);
}
-
+
exit(1);
}
* unmodified if we cannot lock it.
*/
lfp = open(pidfile, O_WRONLY|O_CREAT, 0640);
-
+
if (lfp < 0)
Log_fatal("Cannot open PID-file %s for writing", pidfile);
if (setuid(pwd->pw_uid))
Log_fatal("setuid() failed: %s", strerror(errno));
-
+
if (!grp)
grp = getgrgid(gid);
if (!grp)
Log_fatal("getgrgid() failed: %s", strerror(errno));
-
+
Log_info("Switch to user '%s' group '%s'", pwd->pw_name, grp->gr_name);
}
void daemonize()
{
int i;
-
+
if (getppid() == 1)
return; /* already a daemon */
i = fork();
}
if ( i > 0)
exit(0); /* parent exits */
-
+
/* child (daemon) continues */
setsid(); /* obtain a new process group */
for (i = getdtablesize(); i >= 0; --i)
close(i); /* close all descriptors */
-
+
i = open("/dev/null",O_RDWR);
(void)dup(i);
(void)dup(i);
-
+
umask(027); /* set newly created file permissions */
(void)chdir("/");
-
+
}
#ifdef POSIX_PRIORITY_SCHEDULING
char *conffile = NULL, *pidfile = NULL;
int c;
struct utsname utsbuf;
-
+
/* Arguments */
#ifdef POSIX_PRIORITY_SCHEDULING
while ((c = getopt(argc, argv, "drp:c:a:b:ht")) != EOF) {
else
exit(0);
}
-
+
/* Initialize the config subsystem early;
* switch_user() will need to read some config variables as well as logging.
*/
Conf_init(conffile);
-
+
/* Logging to terminal if not daemonizing, otherwise to syslog or log file.
*/
if (!nodaemon) {
/* Reopen log file. If user switch results in access denied, we catch
* it early.
*/
- Log_reset();
+ Log_reset();
}
else Log_init(true);
-
+
signal(SIGCHLD, SIG_IGN); /* ignore child */
signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
signal(SIGTTOU, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, signal_handler); /* catch hangup signal */
signal(SIGTERM, signal_handler); /* catch kill signal */
-
+
/* Build system string */
if (uname(&utsbuf) == 0) {
snprintf(system_string, 64, "%s %s", utsbuf.sysname, utsbuf.machine);
snprintf(system_string, 64, "unknown unknown");
snprintf(version_string, 64, "unknown");
}
-
+
/* Initializing */
SSLi_init();
Chan_init();
if (realtime)
setscheduler();
#endif
-
+
Server_run();
-
+
Ban_deinit();
SSLi_deinit();
Chan_free();
Log_free();
Conf_deinit();
-
+
if (pidfile != NULL)
unlink(pidfile);
-
+
return 0;
}
msg->payload.reject->type = type;
msg->payload.reject->has_type = true;
Client_send_message(client, msg);
-
+
Log_info_client(client, "Server reject reason: %s", reason);
}
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]);
msg->messageType == Version)) {
goto out;
}
-
+
switch (msg->messageType) {
case UDPTunnel:
case Ping:
default:
Timer_restart(&client->idleTime);
}
-
+
switch (msg->messageType) {
case Authenticate:
Log_debug("Authenticate message received");
-
+
if (IS_AUTH(client) || !msg->payload.authenticate->username) {
/* 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'. n_tokens = %d", client->username,
msg->payload.authenticate->n_tokens);
- addTokens(client, msg);
+ addTokens(client, msg);
}
break;
}
-
+
if (SSLi_getSHA1Hash(client->ssl, client->hash) && Ban_isBanned(client)) {
char hexhash[41];
SSLi_hash2hex(client->hash, hexhash);
Log_info("Client with hash '%s' is banned. Disconnecting", hexhash);
goto disconnect;
}
-
+
client->authenticated = true;
-
+
client_itr = NULL;
while (Client_iterate(&client_itr) != NULL) {
if (!IS_AUTH(client_itr))
Log_debug("Username already in use");
sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__UsernameInUse);
goto disconnect;
- }
+ }
}
if (strlen(getStrConf(PASSPHRASE)) > 0) {
if (!msg->payload.authenticate->password ||
msg->payload.authenticate->password : "(null)");
goto disconnect;
}
- }
+ }
if (strlen(msg->payload.authenticate->username) == 0 ||
strlen(msg->payload.authenticate->username) >= MAX_USERNAME) { /* XXX - other invalid names? */
char buf[64];
Log_debug("Invalid username");
sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__InvalidUsername);
goto disconnect;
- }
+ }
if (Client_count() >= getIntConf(MAX_CLIENTS)) {
char buf[64];
sendServerReject(client, buf, MUMBLE_PROTO__REJECT__REJECT_TYPE__ServerFull);
goto disconnect;
}
-
+
/* Name */
- client->username = strdup(msg->payload.authenticate->username);
+ client->username = strdup(msg->payload.authenticate->username);
/* Tokens */
if (msg->payload.authenticate->n_tokens > 0)
addTokens(client, msg);
-
+
/* Check if admin PW among tokens */
if (strlen(getStrConf(ADMIN_PASSPHRASE)) > 0 &&
Client_token_match(client, getStrConf(ADMIN_PASSPHRASE))) {
client->isAdmin = true;
Log_info_client(client, "User provided admin password");
}
-
+
/* Setup UDP encryption */
CryptState_init(&client->cryptState);
CryptState_genKey(&client->cryptState);
/* Channel stuff */
Chan_userJoin(defaultChan, client); /* Join default channel */
- /* Codec version */
+ /* Codec version */
Log_debug("Client %d has %d CELT codecs", client->sessionId,
msg->payload.authenticate->n_celt_versions);
if (msg->payload.authenticate->n_celt_versions > 0) {
int i;
codec_t *codec_itr;
client->codec_count = msg->payload.authenticate->n_celt_versions;
-
+
for (i = 0; i < client->codec_count; i++)
Client_codec_add(client, msg->payload.authenticate->celt_versions[i]);
codec_itr = NULL;
while (Client_codec_iterate(client, &codec_itr) != NULL)
Log_debug("Client %d CELT codec ver 0x%x", client->sessionId, codec_itr->codec);
-
+
} else {
Client_codec_add(client, (int32_t)0x8000000b);
client->codec_count = 1;
}
if (msg->payload.authenticate->opus)
client->bOpus = true;
-
+
recheckCodecVersions(client);
-
+
sendmsg = Msg_create(CodecVersion);
sendmsg->payload.codecVersion->alpha = iCodecAlpha;
sendmsg->payload.codecVersion->beta = iCodecBeta;
sendmsg->payload.channelState->position = ch_itr->position;
}
Log_debug("Send channel info: %s", sendmsg->payload.channelState->name);
- Client_send_message(client, sendmsg);
+ Client_send_message(client, sendmsg);
}
/* Iterate channels and send channel links info */
uint32_t *links;
int i = 0;
struct dlist *itr;
-
+
sendmsg = Msg_create(ChannelState);
sendmsg->payload.channelState->has_channel_id = true;
sendmsg->payload.channelState->channel_id = ch_itr->id;
sendmsg->payload.channelState->n_links = ch_itr->linkcount;
-
+
links = (uint32_t *)malloc(ch_itr->linkcount * sizeof(uint32_t));
list_iterate(itr, &ch_itr->channel_links) { /* Iterate links */
channel_t *ch;
Client_send_message(client, sendmsg);
}
}
-
+
/* Send user state for connecting user to other users */
sendmsg = Msg_create(UserState);
sendmsg->payload.userState->has_session = true;
Client_send_message(client, sendmsg);
/* Server config message */
- sendmsg = Msg_create(ServerConfig);
+ sendmsg = Msg_create(ServerConfig);
sendmsg->payload.serverConfig->has_allow_html = true;
sendmsg->payload.serverConfig->allow_html = true; /* Support this? */
sendmsg->payload.serverConfig->has_message_length = true;
Log_info_client(client, "User %s authenticated", client->username);
break;
-
+
case Ping:
if (msg->payload.ping->has_good)
client->cryptState.uiRemoteGood = msg->payload.ping->good;
client->cryptState.uiRemoteGood, client->cryptState.uiRemoteLate,
client->cryptState.uiRemoteLost, client->cryptState.uiRemoteResync
);
-
+
client->UDPPingAvg = msg->payload.ping->udp_ping_avg;
client->UDPPingVar = msg->payload.ping->udp_ping_var;
client->TCPPingAvg = msg->payload.ping->tcp_ping_avg;
client->TCPPingVar = msg->payload.ping->tcp_ping_var;
client->UDPPackets = msg->payload.ping->udp_packets;
client->TCPPackets = msg->payload.ping->tcp_packets;
-
+
sendmsg = Msg_create(Ping);
sendmsg->payload.ping->timestamp = msg->payload.ping->timestamp;
if (target == NULL)
target = client;
-
+
msg->payload.userState->has_session = true;
msg->payload.userState->session = target->sessionId;
msg->payload.userState->has_actor = true;
client->recording = msg->payload.userState->recording;
char *message;
uint32_t *tree_id;
-
+
message = malloc(strlen(client->username) + 32);
if (!message)
Log_fatal("Out of memory");
Log_fatal("Out of memory");
memcpy(client->context, msg->payload.userState->plugin_context.data,
msg->payload.userState->plugin_context.len);
-
+
break; /* Don't inform other users about this state */
}
/* Re-use message */
Msg_inc_ref(msg);
-
+
Client_send_message_except(NULL, msg);
/* Need to send remove channel message _after_ UserState message */
if (sendmsg != NULL)
Client_send_message_except(NULL, sendmsg);
break;
-
+
case TextMessage:
if (!getBoolConf(ALLOW_TEXTMESSAGE))
break;
sendPermissionDenied(client, "Tree message not supported");
break;
}
-
+
if (msg->payload.textMessage->n_channel_id > 0) { /* To channel */
int i;
channel_t *ch_itr;
Log_debug("Client release %s", client->release);
}
if (msg->payload.version->os) {
- if (client->os) free(client->os);
+ if (client->os) free(client->os);
client->os = strdup(msg->payload.version->os);
Log_debug("Client OS %s", client->os);
}
if (msg->payload.version->os_version) {
- if (client->os_version) free(client->os_version);
+ if (client->os_version) free(client->os_version);
client->os_version = strdup(msg->payload.version->os_version);
Log_debug("Client OS version %s", client->os_version);
}
case PermissionQuery:
Msg_inc_ref(msg); /* Re-use message */
msg->payload.permissionQuery->has_permissions = true;
-
+
if (client->isAdmin)
msg->payload.permissionQuery->permissions = PERM_ADMIN;
else
msg->payload.permissionQuery->permissions = PERM_DEFAULT;
-
+
if (!getBoolConf(ALLOW_TEXTMESSAGE))
msg->payload.permissionQuery->permissions &= ~PERM_TEXTMESSAGE;
if (!getBoolConf(ENABLE_BAN))
msg->payload.permissionQuery->permissions &= ~PERM_BAN;
-
+
Client_send_message(client, msg);
break;
case UDPTunnel:
case ChannelState:
{
channel_t *ch_itr, *parent, *newchan;
- int leave_id;
+ int leave_id;
/* Don't allow any changes to existing channels */
if (msg->payload.channelState->has_channel_id) {
sendPermissionDenied(client, "Not supported by uMurmur");
sendPermissionDenied(client, "Channel name too long");
break;
}
-
+
parent = Chan_fromId(msg->payload.channelState->parent);
if (parent == NULL)
break;
}
if (ch_itr != NULL)
break;
-
+
/* Disallow temporary channels as siblings to temporary channels */
if (parent->temporary) {
sendPermissionDenied(client, "Parent channel is temporary channel");
break;
}
-
+
/* XXX - Murmur looks for "\\w" and sends perm denied if not found.
* I don't know why so I don't do that here...
*/
sendmsg->payload.channelRemove->channel_id = leave_id;
Client_send_message_except(NULL, sendmsg);
}
- }
+ }
break;
case UserStats:
codec_t *codec_itr = NULL;
int i;
bool_t details = true;
-
+
if (msg->payload.userStats->has_stats_only)
details = !msg->payload.userStats->stats_only;
-
+
if (!msg->payload.userStats->has_session)
sendPermissionDenied(client, "Not supported by uMurmur");
while (Client_iterate(&target) != NULL) {
}
if (!target) /* Not found */
break;
-
+
/*
* Differences from Murmur:
* o Ignoring certificates intentionally
* o Ignoring channel local determining
*/
-
+
sendmsg = Msg_create(UserStats);
sendmsg->payload.userStats->session = msg->payload.userStats->session;
sendmsg->payload.userStats->from_client->has_good = true;
sendmsg->payload.userStats->from_client->lost = target->cryptState.uiLost;
sendmsg->payload.userStats->from_client->has_resync = true;
sendmsg->payload.userStats->from_client->resync = target->cryptState.uiResync;
-
+
sendmsg->payload.userStats->from_server->has_good = true;
sendmsg->payload.userStats->from_server->good = target->cryptState.uiRemoteGood;
sendmsg->payload.userStats->from_server->has_late = true;
sendmsg->payload.userStats->udp_ping_avg = target->UDPPingAvg;
sendmsg->payload.userStats->has_udp_ping_var = true;
sendmsg->payload.userStats->udp_ping_var = target->UDPPingVar;
-
+
sendmsg->payload.userStats->has_tcp_ping_avg = true;
sendmsg->payload.userStats->tcp_ping_avg = target->TCPPingAvg;
sendmsg->payload.userStats->has_tcp_ping_var = true;
sendmsg->payload.userStats->tcp_ping_var = target->TCPPingVar;
sendmsg->payload.userStats->has_tcp_packets = true;
sendmsg->payload.userStats->tcp_packets = target->TCPPackets;
-
+
if (details) {
sendmsg->payload.userStats->version->has_version = true;
sendmsg->payload.userStats->version->os = strdup(target->os);
if (target->os_version)
sendmsg->payload.userStats->version->os_version = strdup(target->os_version);
-
+
sendmsg->payload.userStats->n_celt_versions = target->codec_count;
sendmsg->payload.userStats->celt_versions = malloc(sizeof(int32_t) * target->codec_count);
if (!sendmsg->payload.userStats->celt_versions)
/* BW */
sendmsg->payload.userStats->has_bandwidth = true;
sendmsg->payload.userStats->bandwidth = target->availableBandwidth;
-
+
/* Onlinesecs */
sendmsg->payload.userStats->has_onlinesecs = true;
- sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;
+ sendmsg->payload.userStats->onlinesecs = Timer_elapsed(&target->connectTime) / 1000000LL;
/* Idlesecs */
sendmsg->payload.userStats->has_idlesecs = true;
- sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;
+ sendmsg->payload.userStats->idlesecs = Timer_elapsed(&target->idleTime) / 1000000LL;
Client_send_message(client, sendmsg);
}
break;
}
/* Re-use message */
Msg_inc_ref(msg);
-
+
Client_send_message_except(NULL, msg);
Client_close(target);
break;
Ban_putBanList(msg, msg->payload.banList->n_bans);
}
break;
-
+
/* Permission denied for all these messages. Not implemented. */
case ChannelRemove:
case ContextAction:
case QueryUsers:
sendPermissionDenied(client, "Not supported by uMurmur");
break;
-
+
default:
Log_warn("Message %d not handled", msg->messageType);
break;
out:
Msg_free(msg);
return;
-
+
disconnect:
Msg_free(msg);
Client_close(client);
static message_t *Msg_create_nopayload(messageType_t messageType);
static void Msg_addPreamble(uint8_t *buffer, uint16_t type, uint32_t len)
-{
+{
buffer[1] = (type) & 0xff;
buffer[0] = (type >> 8) & 0xff;
-
+
buffer[5] = (len) & 0xff;
buffer[4] = (len >> 8) & 0xff;
buffer[3] = (len >> 16) & 0xff;
- buffer[2] = (len >> 24) & 0xff;
+ buffer[2] = (len >> 24) & 0xff;
}
static void Msg_getPreamble(uint8_t *buffer, int *type, int *len)
{
uint16_t msgType;
uint32_t msgLen;
-
+
msgType = buffer[1] | (buffer[0] << 8);
msgLen = buffer[5] | (buffer[4] << 8) | (buffer[3] << 16) | (buffer[2] << 24);
*type = (int)msgType;
{
int len;
uint8_t *bufptr = buffer + PREAMBLE_SIZE;
-
+
Log_debug("To net: msg type %d", msg->messageType);
switch (msg->messageType) {
case Version:
mumble_proto__channel_remove__pack(msg->payload.channelRemove, bufptr);
break;
case UserStats:
- {
+ {
len = mumble_proto__user_stats__get_packed_size(msg->payload.userStats);
if (len > MAX_MSGSIZE) {
Log_warn("Too big tx message. Discarding");
{
message_t *msg = Msg_create_nopayload(messageType);
int i;
-
+
switch (messageType) {
case Version:
msg->payload.version = malloc(sizeof(MumbleProto__Version));
case UserStats:
msg->payload.userStats = malloc(sizeof(MumbleProto__UserStats));
mumble_proto__user_stats__init(msg->payload.userStats);
-
+
msg->payload.userStats->from_client = malloc(sizeof(MumbleProto__UserStats__Stats));
mumble_proto__user_stats__stats__init(msg->payload.userStats->from_client);
msg->payload.userStats->version = malloc(sizeof(MumbleProto__Version));
mumble_proto__version__init(msg->payload.userStats->version);
-
+
if (!msg->payload.userStats || !msg->payload.userStats->from_client ||
!msg->payload.userStats->from_server || !msg->payload.userStats->version)
Log_fatal("Out of memory");
{
message_t *msg = Msg_create_nopayload(BanList);
int i;
-
+
msg->payload.banList = malloc(sizeof(MumbleProto__BanList));
if (msg->payload.banList == NULL)
Log_fatal("Out of memory");
char *name, char *hash, char *reason, char *start, uint32_t duration)
{
MumbleProto__BanList__BanEntry *entry = msg->payload.banList->bans[index];
-
+
entry->address.data = malloc(16);
if (!entry->address.data)
- Log_fatal("Out of memory");
+ Log_fatal("Out of memory");
memcpy(entry->address.data, address, 16);
entry->address.len = 16;
entry->mask = mask;
entry->reason = strdup(reason);
entry->start = strdup(start);
if (!entry->name || !entry->hash || !entry->reason || !entry->start)
- Log_fatal("Out of memory");
-
+ Log_fatal("Out of memory");
+
if (duration > 0) {
entry->duration = duration;
entry->has_duration = true;
void Msg_free(message_t *msg)
{
int i;
-
+
if (msg->refcount) msg->refcount--;
if (msg->refcount > 0)
return;
message_t *Msg_CreateVoiceMsg(uint8_t *data, int size)
{
message_t *msg = NULL;
-
+
msg = Msg_create_nopayload(UDPTunnel);
msg->unpacked = false;
msg->payload.UDPTunnel = malloc(sizeof(struct _MumbleProto__UDPTunnel));
Log_debug("Message type %d size %d", messageType, msgLen);
//dumpmsg(data, size);
-
+
switch (messageType) {
case Version:
{
break;
}
return msg;
-
+
err_out:
free(msg);
return NULL;
pds->bOk = false;
return 0;
}
-
+
}
static inline uint64_t next(pds_t *pds)
void Pds_add_double(pds_t *pds, double value)
{
double64u_t u;
-
+
u.dval = value;
-
+
Pds_add_numval(pds, u.u64);
}
void Pds_add_numval(pds_t *pds, const uint64_t value)
{
uint64_t i = value;
-
+
if ((i & 0x8000000000000000LL) && (~i < 0x100000000LL)) {
// Signed number.
i = ~i;
append_val(pds, i & 0xFF);
}
}
-
+
uint64_t Pds_get_numval(pds_t *pds)
{
uint64_t i = 0;
uint64_t v = next(pds);
-
+
if ((v & 0x80) == 0x00) {
i=(v & 0x7F);
} else if ((v & 0xC0) == 0x80) {
{
int ret;
pk_context pk;
-
+
pk_init(&pk);
ret = pk_parse_keyfile(&pk, path, pwd);
if (ret == 0 && !pk_can_do( &pk, POLARSSL_PK_RSA))
static void initTestKey()
{
int rc;
-
+
rc = x509parse_key_rsa(&key, (unsigned char *)test_srv_key,
strlen(test_srv_key), NULL, 0);
if (rc != 0)
{
int rc;
char *crtfile = (char *)getStrConf(CERTIFICATE);
-
+
if (crtfile == NULL) {
#ifdef USE_POLARSSL_TESTCERT
Log_warn("No certificate file specified. Falling back to test certificate.");
char *keyfile = (char *)getStrConf(KEY);
if (keyfile == NULL)
- Log_fatal("No key file specified");
+ Log_fatal("No key file specified");
rc = x509parse_keyfile(&key, keyfile, NULL);
if (rc != 0)
Log_fatal("Could not read RSA key file %s", keyfile);
int urandom_bytes(void *ctx, unsigned char *dest, size_t len)
{
int cur;
-
+
while (len) {
cur = read(urandom_fd, dest, len);
if (cur < 0)
void SSLi_init(void)
{
char verstring[12];
-
+
initCert();
#ifdef USE_POLARSSL_TESTCERT
if (builtInTestCertificate) {
if (urandom_fd < 0)
Log_fatal("Cannot open /dev/urandom");
#endif
-
+
version_get_string(verstring);
Log_info("PolarSSL library version %s initialized", verstring);
}
{
#ifdef POLARSSL_API_V1_3_ABOVE
x509_crt_free(&certificate);
-#else
+#else
x509_free(&certificate);
#endif
rsa_free(&key);
#endif
if (!cert) {
return false;
- }
+ }
sha1(cert->raw.p, cert->raw.len, hash);
return true;
}
-
+
SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
{
ssl_context *ssl;
ssl_session *ssn;
int rc;
-
+
ssl = malloc(sizeof(ssl_context));
ssn = malloc(sizeof(ssl_session));
if (!ssl || !ssn)
Log_fatal("Out of memory");
memset(ssl, 0, sizeof(ssl_context));
memset(ssn, 0, sizeof(ssl_session));
-
+
rc = ssl_init(ssl);
if (rc != 0 )
Log_fatal("Failed to initialize: %d", rc);
-
- ssl_set_endpoint(ssl, SSL_IS_SERVER);
+
+ ssl_set_endpoint(ssl, SSL_IS_SERVER);
ssl_set_authmode(ssl, SSL_VERIFY_OPTIONAL);
-
+
#ifdef USE_POLARSSL_HAVEGE
ssl_set_rng(ssl, HAVEGE_RAND, &hs);
#else
ssl_set_rng(ssl, urandom_bytes, NULL);
#endif
-
+
ssl_set_dbg(ssl, pssl_debug, NULL);
ssl_set_bio(ssl, net_recv, fd, net_send, fd);
#else
ssl_set_session(ssl, 0, 0, ssn);
#endif
-
+
ssl_set_ca_chain(ssl, &certificate, NULL, NULL);
#ifdef POLARSSL_API_V1_3_ABOVE
ssl_set_own_cert_rsa(ssl, &certificate, &key);
int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready)
{
int rc;
-
+
rc = ssl_handshake(ssl);
if (rc != 0) {
if (rc == POLARSSL_ERR_NET_WANT_READ || rc == POLARSSL_ERR_NET_WANT_WRITE) {
return 0;
} else if (rc == POLARSSL_ERR_X509_CERT_VERIFY_FAILED) { /* Allow this (selfsigned etc) */
- return 0;
+ return 0;
} else {
Log_warn("SSL handshake failed: %d", rc);
return -1;
int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len)
{
int rc;
-
+
rc = ssl_write(ssl, buf, len);
if (rc == POLARSSL_ERR_NET_WANT_WRITE)
return SSLI_ERROR_WANT_WRITE;
static RSA *rsa;
static SSL_CTX *context;
static EVP_PKEY *pkey;
-
+
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx);
static int SSL_add_ext(X509 * crt, int nid, char *value) {
{
FILE *fp;
X509 *x509;
-
+
/* open the certificate file */
fp = fopen(certfile, "r");
if (fp == NULL) {
Log_warn("Unable to open the X509 file %s for reading.", certfile);
return NULL;
}
-
- /* allocate memory for the cert structure */
+
+ /* allocate memory for the cert structure */
x509 = X509_new();
-
+
if (PEM_read_X509(fp, &x509, NULL, NULL) == 0) {
/* error reading the x509 information - check the error stack */
Log_warn("Error trying to read X509 info.");
Log_warn("Unable to open the private key file %s for reading.", keyfile);
return NULL;
}
-
+
/* allocate memory for the RSA structure */
rsa = RSA_new();
-
+
/* assign a callback function for the password */
-
- /* read a private key from file */
+
+ /* read a private key from file */
if (PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL) <= 0) {
/* error reading the key - check the error stack */
Log_warn("Error trying to read private key.");
static void SSL_writecert(char *certfile, X509 *x509)
{
FILE *fp;
-
+
/* open the private key file */
fp = fopen(certfile, "w");
if (fp == NULL) {
Log_warn("Unable to open the X509 file %s for writing", certfile);
return;
- }
+ }
if (PEM_write_X509(fp, x509) == 0) {
Log_warn("Error trying to write X509 info.");
}
static void SSL_writekey(char *keyfile, RSA *rsa)
{
FILE *fp;
-
+
/* open the private key file for reading */
fp = fopen(keyfile, "w");
if (fp == NULL) {
Log_warn("Unable to open the private key file %s for writing.", keyfile);
return;
}
-
+
if (PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL) == 0) {
Log_warn("Error trying to write private key");
}
static void SSL_initializeCert() {
char *crt, *key, *pass;
-
+
crt = (char *)getStrConf(CERTIFICATE);
key = (char *)getStrConf(KEY);
pass = (char *)getStrConf(PASSPHRASE);
if (rsa != NULL) {
pkey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(pkey, rsa);
- }
+ }
+
-
#if 0
/* Later ... */
- if (key && !x509) {
+ if (key && !x509) {
qscCert = QSslCertificate(key);
if (! qscCert.isNull()) {
logthis("Using certificate from key.");
}
#endif
-
+
if (!rsa || !x509) {
Log_info("Generating new server certificate.");
-
+
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
-
+
x509 = X509_new();
pkey = EVP_PKEY_new();
rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
EVP_PKEY_assign_RSA(pkey, rsa);
-
+
X509_set_version(x509, 2);
ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
X509_gmtime_adj(X509_get_notBefore(x509),0);
X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
X509_set_pubkey(x509, pkey);
-
+
X509_NAME *name=X509_get_subject_name(x509);
-
+
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const uint8_t *)"Murmur Autogenerated Certificate v2", -1, -1, 0);
X509_set_issuer_name(x509, name);
SSL_add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
SSL_add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
SSL_add_ext(x509, NID_subject_key_identifier, "hash");
SSL_add_ext(x509, NID_netscape_comment, "Generated from umurmur");
-
+
X509_sign(x509, pkey, EVP_md5());
-
+
SSL_writecert(crt, x509);
SSL_writekey(key, rsa);
}
STACK_OF(SSL_CIPHER) *cipherlist = NULL, *cipherlist_new = NULL;
SSL_CIPHER *cipher;
char *cipherstring, tempstring[128];
-
+
SSL_library_init();
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
SSL_load_error_strings(); /* load all error messages */
ERR_print_errors_fp(stderr);
abort();
}
-
+
char* sslCAPath = getStrConf(CAPATH);
if(sslCAPath != NULL)
{
SSL_CTX_load_verify_locations(context, NULL, sslCAPath);
}
-
+
SSL_initializeCert();
if (SSL_CTX_use_certificate(context, x509) <= 0)
Log_fatal("Failed to initialize cert");
ERR_print_errors_fp(stderr);
Log_fatal("Failed to initialize private key");
}
-
+
/* Set cipher list */
- ssl = SSL_new(context);
+ ssl = SSL_new(context);
cipherlist = (STACK_OF(SSL_CIPHER) *) SSL_get_ciphers(ssl);
cipherlist_new = (STACK_OF(SSL_CIPHER) *) sk_SSL_CIPHER_new_null();
-
+
for ( i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist, i)) != NULL; i++) {
if (SSL_CIPHER_get_bits(cipher, NULL) >= 128) {
sk_SSL_CIPHER_push(cipherlist_new, cipher);
offset += sprintf(cipherstring + offset, "%s:", SSL_CIPHER_get_name(cipher));
}
}
-
+
if (cipherlist_new)
sk_SSL_CIPHER_free(cipherlist_new);
-
+
if (strlen(cipherstring) == 0)
Log_fatal("No suitable ciphers found!");
-
+
if (SSL_CTX_set_cipher_list(context, cipherstring) == 0)
Log_fatal("Failed to set cipher list!");
free(cipherstring);
-
+
SSL_CTX_set_verify(context, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
- verify_callback);
-
+ verify_callback);
+
SSL_free(ssl);
Log_info("OpenSSL library initialized");
SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
{
SSL *ssl;
-
+
*SSLready = false;
ssl = SSL_new(context);
SSL_set_fd(ssl, *fd);
X509 *x509;
uint8_t *buf, *p;
int len;
-
+
x509 = SSL_get_peer_certificate(ssl);
if (!x509) {
return false;
- }
-
+ }
+
len = i2d_X509(x509, NULL);
buf = malloc(len);
if (buf == NULL) {
}
p = buf;
- i2d_X509(x509, &p);
-
+ i2d_X509(x509, &p);
+
SHA1(buf, len, hash);
free(buf);
return true;
}
-
+
void SSLi_closeconnection(SSL_handle_t *ssl)
{
SSL_free(ssl);
X509 *err_cert;
int err, depth;
SSL *ssl;
-
+
err_cert = X509_STORE_CTX_get_current_cert(ctx);
err = X509_STORE_CTX_get_error(ctx);
depth = X509_STORE_CTX_get_error_depth(ctx);
-
+
ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
-
+
if (depth > 5) {
preverify_ok = 0;
err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
}
return 1;
}
-
+
#endif
{
struct dlist *itr;
voicetarget_t *vt;
-
+
list_iterate(itr, &client->voicetargets) {
if (targetId == list_get_entry(itr, voicetarget_t, node)->id) {
int i;
{
struct dlist *itr;
voicetarget_t *vt;
-
+
list_iterate(itr, &client->voicetargets) {
if (targetId == list_get_entry(itr, voicetarget_t, node)->id) {
int i;
}
}
}
- }
+ }
}
void Voicetarget_add_id(client_t *client, int targetId)
{
voicetarget_t *newtarget;
int i;
-
+
Voicetarget_del_id(client, targetId);
newtarget = malloc(sizeof(voicetarget_t));
if (!newtarget)