Skip to content

Instantly share code, notes, and snippets.

@mkmik
Created February 7, 2016 13:13
Show Gist options
  • Save mkmik/cc4b0cbf1e728cf38705 to your computer and use it in GitHub Desktop.
Save mkmik/cc4b0cbf1e728cf38705 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include "common/md5.h"
// __builtin_types_compatible_p
/////////////////////////////////////
// some preprocessor magic
// double indirection needed to concatenate two macro expansions
#define M_CONCAT(x, y) M_PASTER(x, y)
#define M_PASTER(x, y) x##y
/////////////////////////////////////
// hack to detect empty vararg
// based on a majestic hack found in
// http://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
// kudos to Jens Gustedt.
#define _ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \
_14, _15, ...) \
_15
#define HAS_COMMA(...) \
_ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
#define _TRIGGER_PARENTHESIS_(...) ,
#define ISEMPTY(...) \
_ISEMPTY(/* test if there is just one argument, eventually an empty \
one */ \
HAS_COMMA(__VA_ARGS__), /* test if _TRIGGER_PARENTHESIS_ together \
with the argument \
adds a comma */ \
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__), /* test if the \
argument together \
with a parenthesis \
adds a comma */ \
HAS_COMMA(__VA_ARGS__(/*empty*/)), /* test if placing it between \
_TRIGGER_PARENTHESIS_ and the \
parenthesis adds a comma */ \
HAS_COMMA(_TRIGGER_PARENTHESIS_ __VA_ARGS__(/*empty*/)))
#define _IS_EMPTY_CASE_0001 ,
#define PASTE5(_0, _1, _2, _3, _4) _0##_1##_2##_3##_4
#define _ISEMPTY(_0, _1, _2, _3) \
HAS_COMMA(PASTE5(_IS_EMPTY_CASE_, _0, _1, _2, _3))
////////// REAL CODE
#define _MD5_COND_1(iftrue, iffalse) iftrue
#define _MD5_COND_0(iftrue, iffalse) iffalse
#define _MD5_IF_LAST(iftrue, iffalse, eat, ...) \
M_CONCAT(_MD5_COND_, ISEMPTY(__VA_ARGS__))(iftrue, iffalse)
#define _MD5_SENTINEL(...) NULL
#define _STATIC_ASSERT(COND, MSG) \
typedef char static_assertion_##MSG[2 * (!!(COND)) - 1]
#define _MD5_CHECK_LEN(len) \
({ \
_STATIC_ASSERT(sizeof(typeof(len)) == sizeof(size_t), \
LENGTH_MUST_BE_SIZE_T); \
static_assertion_LENGTH_MUST_BE_SIZE_T dummy; \
(void) dummy; \
len; \
})
#define safe_md5_args_9(p, len, ...) ___BAD_ARGLIST_TOO_LONG
#define safe_md5_args_8(p, len, ...) \
p, _MD5_CHECK_LEN(len), \
_MD5_IF_LAST(_MD5_SENTINEL, safe_md5_args_9, __VA_ARGS__)(__VA_ARGS__)
#define safe_md5_args_7(p, len, ...) \
p, _MD5_CHECK_LEN(len), \
_MD5_IF_LAST(_MD5_SENTINEL, safe_md5_args_8, __VA_ARGS__)(__VA_ARGS__)
#define safe_md5_args_6(p, len, ...) \
p, _MD5_CHECK_LEN(len), \
_MD5_IF_LAST(_MD5_SENTINEL, safe_md5_args_7, __VA_ARGS__)(__VA_ARGS__)
#define safe_md5_args_5(p, len, ...) \
p, _MD5_CHECK_LEN(len), \
_MD5_IF_LAST(_MD5_SENTINEL, safe_md5_args_6, __VA_ARGS__)(__VA_ARGS__)
#define safe_md5_args_4(p, len, ...) \
p, _MD5_CHECK_LEN(len), \
_MD5_IF_LAST(_MD5_SENTINEL, safe_md5_args_5, __VA_ARGS__)(__VA_ARGS__)
#define safe_md5_args_3(p, len, ...) \
p, _MD5_CHECK_LEN(len), \
_MD5_IF_LAST(_MD5_SENTINEL, safe_md5_args_4, __VA_ARGS__)(__VA_ARGS__)
#define safe_md5_args_2(p, len, ...) \
p, _MD5_CHECK_LEN(len), \
_MD5_IF_LAST(_MD5_SENTINEL, safe_md5_args_3, __VA_ARGS__)(__VA_ARGS__)
#define safe_md5_args_1(p, len, ...) \
p, _MD5_CHECK_LEN(len), \
_MD5_IF_LAST(_MD5_SENTINEL, safe_md5_args_2, __VA_ARGS__)(__VA_ARGS__)
#define safe_md5_args(p, len, ...) \
p, _MD5_CHECK_LEN(len), \
_MD5_IF_LAST(_MD5_SENTINEL, safe_md5_args_1, __VA_ARGS__)(__VA_ARGS__)
#define safe_cs_md5(ha1, ...) cs_md5(ha1, safe_md5_args(__VA_ARGS__))
static void add_pw_line(char ha1[33], const char *user, const char *domain,
const char *pass) {
safe_cs_md5(ha1, user, strlen(user), ":", (size_t)1, domain, strlen(domain),
":", (size_t)1, pass, strlen(pass), NULL);
printf("%s:%s:%s\n", user, domain, ha1);
}
int main() {
char ha1[33];
add_pw_line(ha1, "joe", "cesanta.com", "bloggs");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment