/* * cc -DTESTING -I ../include/ hmac.c md5.c -o hmac * * ./hmac Jefe "what do ya want for nothing?" */ int main(int argc, char **argv) { uint8_t digest[16]; char *key; int key_len; char *text; int text_len; int i; key = argv[1]; key_len = strlen(key); text = argv[2]; text_len = strlen(text); fr_hmac_md5(digest, text, text_len, key, key_len); for (i = 0; i < 16; i++) { printf("%02x", digest[i]); } printf("\n"); exit(0); return 0; }
static ssize_t do_challenge(int sockfd) { ssize_t r; fr_channel_type_t channel; uint8_t challenge[16]; challenge[0] = 0; /* * When connecting over a socket, the server challenges us. */ r = fr_channel_read(sockfd, &channel, challenge, sizeof(challenge)); if (r <= 0) return r; if ((r != 16) || (channel != FR_CHANNEL_AUTH_CHALLENGE)) { fprintf(stderr, "%s: Failed to read challenge.\n", progname); exit(1); } fr_hmac_md5(challenge, (uint8_t const *) secret, strlen(secret), challenge, sizeof(challenge)); r = fr_channel_write(sockfd, FR_CHANNEL_AUTH_RESPONSE, challenge, sizeof(challenge)); if (r <= 0) return r; /* * If the server doesn't like us, he just closes the * socket. So we don't look for an ACK. */ return r; }
/** Generate the HMAC-MD5 of a string or attribute * * Example: "%{hmacmd5:foo bar}" == "Zm9v" */ static ssize_t hmac_md5_xlat(UNUSED void *instance, UNUSED REQUEST *request, char const *fmt, char *out, size_t outlen) { uint8_t const *data, *key; char const *p; ssize_t data_len, key_len; uint8_t digest[MD5_DIGEST_LENGTH]; char data_ref[256]; if (outlen <= (sizeof(digest) * 2)) { REDEBUG("Insufficient space to write digest, needed %zu bytes, have %zu bytes", (sizeof(digest) * 2) + 1, outlen); return -1; } p = strchr(fmt, ' '); if (!p) { REDEBUG("HMAC requires exactly two arguments (&data &key)"); return -1; } if ((size_t)(p - fmt) >= sizeof(data_ref)) { REDEBUG("Insufficient space to store HMAC input data, needed %zu bytes, have %zu bytes", (p - fmt) + 1, sizeof(data_ref)); return -1; } strlcpy(data_ref, fmt, (p - fmt) + 1); data_len = xlat_fmt_to_ref(&data, request, data_ref); if (data_len < 0) return -1; while (isspace(*p) && p++); key_len = xlat_fmt_to_ref(&key, request, p); if (key_len < 0) return -1; fr_hmac_md5(digest, data, data_len, key, key_len); return fr_bin2hex(out, digest, sizeof(digest)); }
static void do_challenge(int sockfd) { size_t total; ssize_t r; uint8_t challenge[16]; for (total = 0; total < sizeof(challenge); ) { r = read(sockfd, challenge + total, sizeof(challenge) - total); if (r == 0) exit(1); if (r < 0) { #ifdef ECONNRESET if (errno == ECONNRESET) { fprintf(stderr, "%s: Connection reset", progname); exit(1); } #endif if (errno == EINTR) continue; fprintf(stderr, "%s: Failed reading data: %s\n", progname, fr_syserror(errno)); exit(1); } total += r; fflush(stdout); } fr_hmac_md5(challenge, (uint8_t const *) secret, strlen(secret), challenge, sizeof(challenge)); if (write(sockfd, challenge, sizeof(challenge)) < 0) { fprintf(stderr, "%s: Failed writing challenge data: %s\n", progname, fr_syserror(errno)); } }