summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/const_array.hpp2
-rw-r--r--src/common/md5calc.cpp108
-rw-r--r--src/common/mmo.hpp2
-rw-r--r--src/common/socket.cpp4
-rw-r--r--src/common/socket.hpp79
-rw-r--r--src/common/utils.hpp39
6 files changed, 178 insertions, 56 deletions
diff --git a/src/common/const_array.hpp b/src/common/const_array.hpp
index 06045dc..a3a6d58 100644
--- a/src/common/const_array.hpp
+++ b/src/common/const_array.hpp
@@ -126,6 +126,8 @@ public:
};
// subclass just provides a simpler name and some conversions
+// Important note: it must be safe to dereference end, though
+// the value is unspecified.
class const_string : public const_array<char>
{
public:
diff --git a/src/common/md5calc.cpp b/src/common/md5calc.cpp
index 36f220d..f773c9f 100644
--- a/src/common/md5calc.cpp
+++ b/src/common/md5calc.cpp
@@ -3,6 +3,7 @@
#include <cstring>
#include "random.hpp"
+#include "utils.hpp"
#include "../poison.hpp"
@@ -43,7 +44,7 @@ const uint32_t T[64] =
static
uint32_t rotate_left(uint32_t val, unsigned shift)
{
- return val << shift | val >> (32-shift);
+ return val << shift | val >> (32 - shift);
}
static
@@ -117,45 +118,45 @@ void MD5_init(MD5_state* state)
void MD5_do_block(MD5_state* state, MD5_block block)
{
#define X block.data
-#define a state->val[(16-i)%4]
-#define b state->val[(17-i)%4]
-#define c state->val[(18-i)%4]
-#define d state->val[(19-i)%4]
+#define a state->val[(16 - i) % 4]
+#define b state->val[(17 - i) % 4]
+#define c state->val[(18 - i) % 4]
+#define d state->val[(19 - i) % 4]
// save the values
const MD5_state saved = *state;
// round 1
- for (int i=0; i<16; i++)
+ for (int i = 0; i < 16; i++)
{
#define k MD5_round1[i].k
#define s MD5_round1[i].s
- a = b + rotate_left(a + F(b,c,d) + X[k] + T[i+0x0], s);
+ a = b + rotate_left(a + F(b, c, d) + X[k] + T[i + 0x0], s);
#undef k
#undef s
}
// round 2
- for (int i=0; i<16; i++)
+ for (int i = 0; i < 16; i++)
{
#define k MD5_round2[i].k
#define s MD5_round2[i].s
- a = b + rotate_left(a + G(b,c,d) + X[k] + T[i+0x10], s);
+ a = b + rotate_left(a + G(b, c, d) + X[k] + T[i + 0x10], s);
#undef k
#undef s
}
// round 3
- for (int i=0; i<16; i++)
+ for (int i = 0; i < 16; i++)
{
#define k MD5_round3[i].k
#define s MD5_round3[i].s
- a = b + rotate_left(a + H(b,c,d) + X[k] + T[i+0x20], s);
+ a = b + rotate_left(a + H(b, c, d) + X[k] + T[i + 0x20], s);
#undef k
#undef s
}
// round 4
- for (int i=0; i<16; i++)
+ for (int i = 0; i < 16; i++)
{
#define k MD5_round4[i].k
#define s MD5_round4[i].s
- a = b + rotate_left(a + I(b,c,d) + X[k] + T[i+0x30], s);
+ a = b + rotate_left(a + I(b, c, d) + X[k] + T[i + 0x30], s);
#undef k
#undef s
}
@@ -172,8 +173,8 @@ void MD5_do_block(MD5_state* state, MD5_block block)
void MD5_to_bin(MD5_state state, uint8_t out[0x10])
{
- for (int i=0; i<0x10; i++)
- out[i] = state.val[i/4] >> 8*(i%4);
+ for (int i = 0; i < 0x10; i++)
+ out[i] = state.val[i / 4] >> 8 * (i % 4);
}
static
@@ -183,9 +184,9 @@ void MD5_to_str(MD5_state state, char out[0x21])
{
uint8_t bin[16];
MD5_to_bin(state, bin);
- for (int i=0; i<0x10; i++)
- out[2*i] = hex[bin[i] >> 4],
- out[2*i+1] = hex[bin[i] & 0xf];
+ for (int i = 0; i < 0x10; i++)
+ out[2 * i] = hex[bin[i] >> 4],
+ out[2 * i + 1] = hex[bin[i] & 0xf];
out[0x20] = '\0';
}
@@ -197,31 +198,31 @@ MD5_state MD5_from_string(const char* msg, const size_t msglen)
size_t rem = msglen;
while (rem >= 64)
{
- for (int i=0; i<0x10; i++)
- X[i] = msg[4*i+0] | msg[4*i+1]<<8 | msg[4*i+2]<<16 | msg[4*i+3]<<24;
+ for (int i = 0; i < 0x10; i++)
+ X[i] = msg[4 * i + 0] | msg[4 * i + 1] << 8 | msg[4 * i + 2] << 16 | msg[4 * i + 3] << 24;
MD5_do_block(&state, block);
msg += 64;
rem -= 64;
}
// now pad 1-512 bits + the 64-bit length - may be two blocks
uint8_t buf[0x40] = {};
- memcpy(buf, msg, rem);
+ really_memcpy(buf, reinterpret_cast<const uint8_t *>(msg), rem);
buf[rem] = 0x80; // a single one bit
if (64 - rem > 8)
{
- for (int i=0; i<8; i++)
- buf[0x38+i] = (static_cast<uint64_t>(msglen)*8) >> (i*8);
+ for (int i = 0; i < 8; i++)
+ buf[0x38 + i] = (static_cast<uint64_t>(msglen) * 8) >> (i * 8);
}
- for (int i=0; i<0x10; i++)
- X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
+ for (int i = 0; i < 0x10; i++)
+ X[i] = buf[4 * i + 0] | buf[4 * i + 1] << 8 | buf[4 * i + 2] << 16 | buf[4 * i + 3] << 24;
MD5_do_block(&state, block);
if (64 - rem <= 8)
{
- memset(buf,'\0', 0x38);
- for (int i=0; i<8; i++)
- buf[0x38+i] = (static_cast<uint64_t>(msglen)*8) >> (i*8);
- for (int i=0; i<0x10; i++)
- X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
+ really_memset0(buf, 0x38);
+ for (int i = 0; i < 8; i++)
+ buf[0x38 + i] = (static_cast<uint64_t>(msglen) * 8) >> (i * 8);
+ for (int i = 0; i < 0x10; i++)
+ X[i] = buf[4 * i + 0] | buf[4 * i + 1] << 8 | buf[4 * i + 2] << 16 | buf[4 * i + 3] << 24;
MD5_do_block(&state, block);
}
return state;
@@ -233,7 +234,8 @@ MD5_state MD5_from_cstring(const char* msg)
return MD5_from_string(msg, strlen(msg));
}
-MD5_state MD5_from_FILE(FILE* in) {
+MD5_state MD5_from_FILE(FILE* in)
+{
uint64_t total_len = 0;
uint8_t buf[0x40];
@@ -249,33 +251,33 @@ MD5_state MD5_from_FILE(FILE* in) {
size_t rv = fread(buf + block_len, 1, 0x40 - block_len, in);
if (!rv)
break;
- total_len += 8*rv; // in bits
+ total_len += 8 * rv; // in bits
block_len += rv;
if (block_len != 0x40)
continue;
- for (int i=0; i<0x10; i++)
- X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
+ for (int i = 0; i < 0x10; i++)
+ X[i] = buf[4 * i + 0] | buf[4 * i + 1] << 8 | buf[4 * i + 2] << 16 | buf[4 * i + 3] << 24;
MD5_do_block(&state, block);
block_len = 0;
}
// no more input, just pad and append the length
buf[block_len] = 0x80;
- memset(buf + block_len + 1, '\0', 0x40 - block_len - 1);
+ really_memset0(buf + block_len + 1, 0x40 - block_len - 1);
if (block_len < 0x38)
{
- for (int i=0; i<8; i++)
- buf[0x38+i] = total_len >> i*8;
+ for (int i = 0; i < 8; i++)
+ buf[0x38 + i] = total_len >> i * 8;
}
- for (int i=0; i<0x10; i++)
- X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
+ for (int i = 0; i < 0x10; i++)
+ X[i] = buf[4 * i + 0] | buf[4 * i + 1] << 8 | buf[4 * i + 2] << 16 | buf[4 * i + 3] << 24;
MD5_do_block(&state, block);
if (0x38 <= block_len)
{
- memset(buf, '\0', 0x38);
- for (int i=0; i<8; i++)
- buf[0x38+i] = total_len >> i*8;
- for (int i=0; i<0x10; i++)
- X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24;
+ really_memset0(buf, 0x38);
+ for (int i = 0; i < 8; i++)
+ buf[0x38 + i] = total_len >> i * 8;
+ for (int i = 0; i < 0x10; i++)
+ X[i] = buf[4 * i + 0] | buf[4 * i + 1] << 8 | buf[4 * i + 2] << 16 | buf[4 * i + 3] << 24;
MD5_do_block(&state, block);
}
return state;
@@ -291,19 +293,20 @@ const char *MD5_saltcrypt(const char *key, const char *salt)
// hash the key then the salt
// buf ends up as a 64-char NUL-terminated string
MD5_to_str(MD5_from_cstring(key), buf);
- MD5_to_str(MD5_from_cstring(salt), buf+32);
+ MD5_to_str(MD5_from_cstring(salt), buf + 32);
// Hash the buffer back into sbuf - this is stupid
// (luckily, putting the result into itself is safe)
- MD5_to_str(MD5_from_cstring(buf), buf+32);
+ MD5_to_str(MD5_from_cstring(buf), buf + 32);
static char obuf[33];
// This truncates the string, but we have to keep it like that for compatibility
- snprintf(obuf, 32, "!%s$%s", salt, buf+32);
+ snprintf(obuf, 32, "!%s$%s", salt, buf + 32);
return obuf;
}
-const char *make_salt(void) {
+const char *make_salt(void)
+{
static char salt[6];
for (int i = 0; i < 5; i++)
// 126 would probably actually be okay
@@ -311,7 +314,8 @@ const char *make_salt(void) {
return salt;
}
-bool pass_ok(const char *password, const char *crypted) {
+bool pass_ok(const char *password, const char *crypted)
+{
char buf[40];
strncpy(buf, crypted, 40);
char *salt = buf + 1;
@@ -324,15 +328,15 @@ bool pass_ok(const char *password, const char *crypted) {
// to return a hopefully unique masked IP.
struct in_addr MD5_ip(char *secret, struct in_addr ip)
{
- char ipbuf[32];
uint8_t obuf[16];
- union {
+ union
+ {
uint8_t bytes[4];
struct in_addr ip;
} conv;
// MD5sum a secret + the IP address
- memset(&ipbuf, 0, sizeof(ipbuf));
+ char ipbuf[32] {};
snprintf(ipbuf, sizeof(ipbuf), "%u%s", ip.s_addr, secret);
/// TODO stop it from being a cstring
MD5_to_bin(MD5_from_cstring(ipbuf), obuf);
diff --git a/src/common/mmo.hpp b/src/common/mmo.hpp
index a04fd34..14b8bac 100644
--- a/src/common/mmo.hpp
+++ b/src/common/mmo.hpp
@@ -78,7 +78,7 @@ struct item
struct point
{
- char map[24];
+ char map_[16];
short x, y;
};
diff --git a/src/common/socket.cpp b/src/common/socket.cpp
index 0ee8712..c509825 100644
--- a/src/common/socket.cpp
+++ b/src/common/socket.cpp
@@ -38,7 +38,7 @@ std::array<std::unique_ptr<struct socket_data>, FD_SETSIZE> session;
inline
void RFIFOFLUSH(int fd)
{
- memmove(&session[fd]->rdata[0], RFIFOP(fd, 0), RFIFOREST(fd));
+ really_memmove(&session[fd]->rdata[0], static_cast<const uint8_t *>(RFIFOP(fd, 0)), RFIFOREST(fd));
session[fd]->rdata_size = RFIFOREST(fd);
session[fd]->rdata_pos = 0;
}
@@ -97,7 +97,7 @@ void send_from_fifo(int fd)
session[fd]->wdata_size -= len;
if (session[fd]->wdata_size)
{
- memmove(&session[fd]->wdata[0], &session[fd]->wdata[len],
+ really_memmove(&session[fd]->wdata[0], &session[fd]->wdata[len],
session[fd]->wdata_size);
}
session[fd]->connected = 1;
diff --git a/src/common/socket.hpp b/src/common/socket.hpp
index d526379..ef7b193 100644
--- a/src/common/socket.hpp
+++ b/src/common/socket.hpp
@@ -102,6 +102,13 @@ FILE *fopen_(const char *path, const char *mode);
bool free_fds(void);
+template<class T>
+uint8_t *pod_addressof(T& structure)
+{
+ static_assert(is_trivially_copyable<T>::value, "Can only byte-copy POD-ish structs");
+ return &reinterpret_cast<uint8_t&>(structure);
+}
+
/// Check how much can be read
@@ -131,6 +138,21 @@ uint32_t RFIFOL(int fd, size_t pos)
{
return *static_cast<const uint32_t *>(RFIFOP(fd, pos));
}
+template<class T>
+void RFIFO_STRUCT(int fd, size_t pos, T& structure)
+{
+ really_memcpy(pod_addressof(structure), static_cast<const uint8_t *>(RFIFOP(fd, pos)), sizeof(T));
+}
+inline
+void RFIFO_STRING(int fd, size_t pos, char *out, size_t len)
+{
+ strzcpy(out, static_cast<const char *>(RFIFOP(fd, pos)), len);
+}
+inline
+void RFIFO_BUF_CLONE(int fd, uint8_t *buf, size_t len)
+{
+ really_memcpy(buf, static_cast<const uint8_t *>(RFIFOP(fd, 0)), len);
+}
/// Done reading
void RFIFOSKIP(int fd, size_t len);
@@ -156,6 +178,16 @@ uint32_t RBUFL(const uint8_t *p, size_t pos)
{
return *static_cast<const uint32_t *>(RBUFP(p, pos));
}
+template<class T>
+void RBUF_STRUCT(const uint8_t *p, size_t pos, T& structure)
+{
+ really_memcpy(pod_addressof(structure), p + pos, sizeof(T));
+}
+inline
+void RBUF_STRING(const uint8_t *p, size_t pos, char *out, size_t len)
+{
+ strzcpy(out, static_cast<const char *>(RBUFP(p, pos)), len);
+}
/// Unused - check how much data can be written
@@ -185,6 +217,29 @@ uint32_t& WFIFOL(int fd, size_t pos)
{
return *static_cast<uint32_t *>(WFIFOP(fd, pos));
}
+template<class T>
+void WFIFO_STRUCT(int fd, size_t pos, T& structure)
+{
+ really_memcpy(static_cast<uint8_t *>(WFIFOP(fd, pos)), pod_addressof(structure), sizeof(T));
+}
+inline
+void WFIFO_STRING(int fd, size_t pos, const char *s, size_t len)
+{
+ strzcpy(static_cast<char *>(WFIFOP(fd, pos)), s, len);
+}
+inline
+void WFIFO_ZERO(int fd, size_t pos, size_t len)
+{
+ uint8_t *b = static_cast<uint8_t *>(WFIFOP(fd, pos));
+ uint8_t *e = b + len;
+ std::fill(b, e, '\0');
+}
+inline
+void WFIFO_BUF_CLONE(int fd, const uint8_t *buf, size_t len)
+{
+ really_memcpy(static_cast<uint8_t *>(WFIFOP(fd, 0)), buf, len);
+}
+
/// Finish writing
void WFIFOSET(int fd, size_t len);
@@ -209,5 +264,29 @@ uint32_t& WBUFL(uint8_t *p, size_t pos)
{
return *static_cast<uint32_t *>(WBUFP(p, pos));
}
+template<class T>
+void WBUF_STRUCT(uint8_t *p, size_t pos, T& structure)
+{
+ really_memcpy(p + pos, pod_addressof(structure), sizeof(T));
+}
+inline
+void WBUF_STRING(uint8_t *p, size_t pos, const char *s, size_t len)
+{
+ strzcpy(static_cast<char *>(WBUFP(p, pos)), s, len);
+}
+inline
+void WBUF_ZERO(uint8_t *p, size_t pos, size_t len)
+{
+ uint8_t *b = static_cast<uint8_t *>(WBUFP(p, pos));
+ uint8_t *e = b + len;
+ std::fill(b, e, '\0');
+}
+
+inline
+void RFIFO_WFIFO_CLONE(int rfd, int wfd, size_t len)
+{
+ really_memcpy(static_cast<uint8_t *>(WFIFOP(wfd, 0)),
+ static_cast<const uint8_t *>(RFIFOP(rfd, 0)), len);
+}
#endif // SOCKET_HPP
diff --git a/src/common/utils.hpp b/src/common/utils.hpp
index caa39ed..cd45aa1 100644
--- a/src/common/utils.hpp
+++ b/src/common/utils.hpp
@@ -7,11 +7,21 @@
#include <cstring>
#include <string>
+#include <type_traits>
#include "const_array.hpp"
#include "operators.hpp"
#include "utils2.hpp"
+template<class T>
+struct is_trivially_copyable
+: std::integral_constant<bool,
+ // come back when GCC actually implements the public traits properly
+ __has_trivial_copy(T)
+ && __has_trivial_assign(T)
+ && __has_trivial_destructor(T)>
+{};
+
int remove_control_chars(char *str);
int e_mail_check(const char *email);
int config_switch (const char *str);
@@ -25,10 +35,37 @@ void strzcpy(char *dest, const char *src, size_t n)
if (n)
{
strncpy(dest, src, n);
- dest[n-1] = '\0';
+ dest[n - 1] = '\0';
}
}
+inline
+void really_memcpy(uint8_t *dest, const uint8_t *src, size_t n)
+{
+ memcpy(dest, src, n);
+}
+
+inline
+void really_memmove(uint8_t *dest, const uint8_t *src, size_t n)
+{
+ memmove(dest, src, n);
+}
+
+inline
+void really_memset0(uint8_t *dest, size_t n)
+{
+ memset(dest, '\0', n);
+}
+template<class T>
+void really_memzero_this(T *v)
+{
+ static_assert(is_trivially_copyable<T>::value, "only for mostly-pod types");
+ static_assert(std::is_class<T>::value || std::is_union<T>::value, "Only for user-defined structures (for now)");
+ memset(v, '\0', sizeof(*v));
+}
+template<class T, size_t n>
+void really_memzero_this(T (&)[n]) = delete;
+
// Exists in place of time_t, to give it a predictable printf-format.
// (on x86 and amd64, time_t == long, but not on x32)
static_assert(sizeof(long long) >= sizeof(time_t), "long long >= time_t");