diff options
Diffstat (limited to 'src/common/util.c')
-rw-r--r-- | src/common/util.c | 94 |
1 files changed, 83 insertions, 11 deletions
diff --git a/src/common/util.c b/src/common/util.c index 29a0f3ed..52464621 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1886,7 +1886,7 @@ int main (int argc, char *argv[]) list = get_subdirs ("foo"); display_list (list); #if GLIB_CHECK_VERSION(2,28,0) - g_slist_free_full (list, (GFunc) g_free); + g_slist_free_full (list, (GDestroyNotify) g_free); #else g_slist_foreach (list, (GFunc) g_free, NULL); g_slist_free (list); @@ -1931,19 +1931,15 @@ get_subdirs (const char *path) char * encode_sasl_pass (char *user, char *pass) { - int passlen; + int authlen; char *buffer; char *encoded; - /* passphrase generation, nicely copy-pasted from the CAP-SASL plugin */ - passlen = strlen (user) * 2 + 2 + strlen (pass); - buffer = (char*) malloc (passlen + 1); - strcpy (buffer, user); - strcpy (buffer + strlen (user) + 1, user); - strcpy (buffer + strlen (user) * 2 + 2, pass); - encoded = g_base64_encode ((unsigned char*) buffer, passlen); - - free (buffer); + /* we can't call strlen() directly on buffer thanks to the atrocious \0 characters it requires */ + authlen = strlen (user) * 2 + 2 + strlen (pass); + buffer = g_strdup_printf ("%s%c%s%c%s", user, '\0', user, '\0', pass); + encoded = g_base64_encode ((unsigned char*) buffer, authlen); + g_free (buffer); return encoded; } @@ -1978,3 +1974,79 @@ find_font (const char *fontname) return 0; } #endif + +static char * +str_sha256hash (char *string) +{ + int i; + unsigned char hash[SHA256_DIGEST_LENGTH]; + char buf[SHA256_DIGEST_LENGTH * 2 + 1]; /* 64 digit hash + '\0' */ + SHA256_CTX sha256; + + SHA256_Init (&sha256); + SHA256_Update (&sha256, string, strlen (string)); + SHA256_Final (hash, &sha256); + + for (i = 0; i < SHA256_DIGEST_LENGTH; i++) + { + sprintf (buf + (i * 2), "%02x", hash[i]); + } + + buf[SHA256_DIGEST_LENGTH * 2] = 0; + + return g_strdup (buf); +} + +/** + * \brief Generate CHALLENGEAUTH response for QuakeNet login. + * + * \param username QuakeNet user name + * \param password password for the user + * \param challenge the CHALLENGE response we got from Q + * + * After a successful connection to QuakeNet a CHALLENGE is requested from Q. + * Generate the CHALLENGEAUTH response from this CHALLENGE and our user + * credentials as per the + * <a href="http://www.quakenet.org/development/challengeauth">CHALLENGEAUTH</a> + * docs. As for using OpenSSL HMAC, see + * <a href="http://www.askyb.com/cpp/openssl-hmac-hasing-example-in-cpp/">example 1</a>, + * <a href="http://stackoverflow.com/questions/242665/understanding-engine-initialization-in-openssl">example 2</a>. + */ +char * +challengeauth_response (char *username, char *password, char *challenge) +{ + int i; + char *user; + char *pass; + char *passhash; + char *key; + char *keyhash; + unsigned char *digest; + GString *buf = g_string_new_len (NULL, SHA256_DIGEST_LENGTH * 2); + + user = g_strdup (username); + *user = rfc_tolower (*username); /* convert username to lowercase as per the RFC */ + + pass = g_strndup (password, 10); /* truncate to 10 characters */ + passhash = str_sha256hash (pass); + g_free (pass); + + key = g_strdup_printf ("%s:%s", user, passhash); + g_free (user); + g_free (passhash); + + keyhash = str_sha256hash (key); + g_free (key); + + digest = HMAC (EVP_sha256 (), keyhash, strlen (keyhash), (unsigned char *) challenge, strlen (challenge), NULL, NULL); + g_free (keyhash); + + for (i = 0; i < SHA256_DIGEST_LENGTH; i++) + { + g_string_append_printf (buf, "%02x", (unsigned int) digest[i]); + } + + digest = (unsigned char *) g_string_free (buf, FALSE); + + return (char *) digest; +} |