7 #include <openssl/sha.h>
8 #include <openssl/hmac.h>
13 #define SHA1_HASH_LENGTH 40
15 int main(int argc
, char** argv
)
18 secret
= getenv("TRACKING_SECRET");
20 fprintf(stderr
, "TRACKING_SECRET not set\n");
24 char input_line
[MAX_LINE
];
25 unsigned int hash_length
= SHA_DIGEST_LENGTH
;
26 unsigned char input_hash
[hash_length
];
27 unsigned char expected_hash
[hash_length
];
28 int secret_length
= strlen(secret
);
30 while (fgets(input_line
, MAX_LINE
, stdin
) != NULL
) {
32 char *ip
, *path
, *query
, *response_code
, *unique_id
;
44 /* in the query string, grab the fields we want to verify */
50 while (parse_query_param(&query
, &key
, &value
) >= 0) {
51 if (strcmp(key
, "id") == 0) {
53 } else if (strcmp(key
, "hash") == 0) {
55 } else if (strcmp(key
, "url") == 0) {
60 if (id
== NULL
|| hash
== NULL
)
63 /* decode the params */
64 int id_length
= url_decode(id
);
68 if (url_decode(hash
) != SHA1_HASH_LENGTH
)
73 url_length
= url_decode(url
);
79 * for clicks just check the response code--validation was done in
80 the click redirect app
81 * for impression pixels check the hash
83 if (strcmp("/click", path
) == 0) {
84 if (strcmp(response_code
, "302") != 0) {
88 /* turn the expected hash into bytes */
89 bool bad_hash
= false;
90 for (int i
= 0; i
< hash_length
; i
++) {
91 int count
= sscanf(&hash
[i
*2], "%2hhx", &input_hash
[i
]);
101 /* generate the expected hash */
104 // NOTE: EMR has openssl <1.0, so these HMAC methods don't return
105 // error codes -- see https://www.openssl.org/docs/crypto/hmac.html
106 HMAC_Init(&ctx
, secret
, secret_length
, EVP_sha1());
107 HMAC_Update(&ctx
, id
, id_length
);
108 HMAC_Final(&ctx
, expected_hash
, &hash_length
);
110 /* check that the hashes match */
111 if (memcmp(input_hash
, expected_hash
, SHA_DIGEST_LENGTH
) != 0)
115 /* split out the fullname and subreddit if necessary */
117 char *subreddit
= NULL
;
119 for (char *c
= id
; *c
!= '\0'; c
++) {
128 fputs(unique_id
, stdout
);
134 fputs(fullname
, stdout
);
137 if (subreddit
!= NULL
) {
138 fputs(subreddit
, stdout
);