END_TEST START_TEST(test_jwt_del_grant) { jwt_t *jwt = NULL; const char *val; const char testval[] = "testing"; int ret = 0; ret = jwt_new(&jwt); ck_assert_int_eq(ret, 0); ck_assert(jwt != NULL); ret = jwt_add_grant(jwt, "iss", testval); ck_assert_int_eq(ret, 0); ret = jwt_del_grant(jwt, "iss"); ck_assert_int_eq(ret, 0); val = jwt_get_grant(jwt, "iss"); ck_assert(val == NULL); /* Delete non existent. */ ret = jwt_del_grant(jwt, "iss"); ck_assert_int_eq(ret, 0); jwt_free(jwt); }
END_TEST START_TEST(test_jwt_encode_alg_none) { const char res[] = "eyJhbGciOiJub25lIn0.eyJhdWQiOiJ3d3cucGx1Z2dlcnM" "ubmwiLCJleHAiOjE0Nzc1MTQ4MTIsInN1YiI6IlBsdWdnZXJzIFNvZnR3YXJlIn0."; jwt_t *jwt = NULL; int ret = 0; char *out; ALLOC_JWT(&jwt); ret = jwt_add_grant(jwt, "aud", "www.pluggers.nl"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant_int(jwt, "exp", 1477514812); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "sub", "Pluggers Software"); ck_assert_int_eq(ret, 0); ret = jwt_set_alg(jwt, JWT_ALG_NONE, NULL, 0); ck_assert_int_eq(ret, 0); out = jwt_encode_str(jwt); ck_assert_ptr_ne(out, NULL); ck_assert_str_eq(out, res); free(out); jwt_free(jwt); }
END_TEST START_TEST(test_jwt_grants_json) { const char *json = "{\"ref\":\"385d6518-fb73-45fc-b649-0527d8576130\"" ",\"id\":\"FVvGYTr3FhiURCFebsBOpBqTbzHdX/DvImiA2yheXr8=\"," "\"iss\":\"localhost\",\"scopes\":\"storage\",\"sub\":" "\"user0\"}"; jwt_t *jwt = NULL; const char *val; int ret = 0; ret = jwt_new(&jwt); ck_assert_int_eq(ret, 0); ck_assert(jwt != NULL); ret = jwt_add_grants_json(jwt, json); ck_assert_int_eq(ret, 0); val = jwt_get_grant(jwt, "ref"); ck_assert(val != NULL); ck_assert_str_eq(val, "385d6518-fb73-45fc-b649-0527d8576130"); jwt_free(jwt); }
END_TEST START_TEST(test_jwt_dump_str) { jwt_t *jwt = NULL; int ret = 0; char *out; ret = jwt_new(&jwt); ck_assert_int_eq(ret, 0); ck_assert(jwt != NULL); ret = jwt_add_grant(jwt, "iss", "files.cyphre.com"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "sub", "user0"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "ref", "XXXX-YYYY-ZZZZ-AAAA-CCCC"); ck_assert_int_eq(ret, 0); out = jwt_dump_str(jwt, 1); ck_assert(out != NULL); free(out); out = jwt_dump_str(jwt, 0); ck_assert(out != NULL); free(out); jwt_free(jwt); }
END_TEST START_TEST(test_jwt_encode_str) { const char res[] = "eyJhbGciOiJub25lIn0.eyJpYXQiOjE0NzU5ODA1NDUsIm" "lzcyI6ImZpbGVzLmN5cGhyZS5jb20iLCJyZWYiOiJYWFhYLVlZWVktWlpa" "Wi1BQUFBLUNDQ0MiLCJzdWIiOiJ1c2VyMCJ9."; jwt_t *jwt = NULL; int ret = 0; char *out; ALLOC_JWT(&jwt); ret = jwt_add_grant(jwt, "iss", "files.cyphre.com"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "sub", "user0"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "ref", "XXXX-YYYY-ZZZZ-AAAA-CCCC"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant_int(jwt, "iat", TS_CONST); ck_assert_int_eq(ret, 0); out = jwt_encode_str(jwt); ck_assert_ptr_ne(out, NULL); ck_assert_str_eq(out, res); free(out); jwt_free(jwt); }
/** * Calculates a Java Web Token (JWT) given the path to a EC private key and * Google Cloud project ID. Returns the JWT as a string that the caller must * free. */ static char* CreateJwt(const char* ec_private_path, const char* project_id) { char iat_time[sizeof(time_t) * 3 + 2]; char exp_time[sizeof(time_t) * 3 + 2]; uint8_t* key = NULL; // Stores the Base64 encoded certificate size_t key_len = 0; jwt_t *jwt = NULL; int ret = 0; char *out = NULL; // Read private key from file FILE *fp = fopen(ec_private_path, "r"); if (fp == (void*) NULL) { printf("Could not open file: %s\n", ec_private_path); return ""; } fseek(fp, 0L, SEEK_END); key_len = ftell(fp); fseek(fp, 0L, SEEK_SET); key = malloc(sizeof(uint8_t) * (key_len + 1)); // certificate length + \0 fread(key, 1, key_len, fp); key[key_len] = '\0'; fclose(fp); // Get JWT parts GetIatExp(iat_time, exp_time, sizeof(iat_time)); jwt_new(&jwt); // Write JWT ret = jwt_add_grant(jwt, "iat", iat_time); if (ret) { printf("Error setting issue timestamp: %d", ret); } ret = jwt_add_grant(jwt, "exp", exp_time); if (ret) { printf("Error setting expiration: %d", ret); } ret = jwt_add_grant(jwt, "aud", project_id); if (ret) { printf("Error adding audience: %d", ret); } ret = jwt_set_alg(jwt, JWT_ALG_ES256, key, key_len); if (ret) { printf("Error during set alg: %d", ret); } out = jwt_encode_str(jwt); // Print JWT if (TRACE) { printf("JWT: [%s]", out); } jwt_free(jwt); free(key); return out; }
END_TEST START_TEST(test_jwt_grants_json) { const char *json = "{\"ref\":\"385d6518-fb73-45fc-b649-0527d8576130\"" ",\"id\":\"FVvGYTr3FhiURCFebsBOpBqTbzHdX/DvImiA2yheXr8=\"," "\"iss\":\"localhost\",\"scopes\":\"storage\",\"sub\":" "\"user0\"}"; const char *json2 = "{" "\"id\":\"FVvGYTr3FhiURCFebsBOpBqTbzHdX/DvImiA2yheXr8=\"," "\"iss\":\"localhost\",\"scopes\":\"storage\",\"sub\":" "\"user0\", \"nbf\":12345678, \"iat\":12346789}"; jwt_t *jwt = NULL; json_t *js_val; const char *val; int intval; int ret = 0; ret = jwt_new(&jwt); ck_assert_int_eq(ret, 0); ck_assert(jwt != NULL); ret = jwt_add_grants_json(jwt, json); ck_assert_int_eq(ret, 0); val = jwt_get_grant(jwt, "ref"); ck_assert(val != NULL); ck_assert_str_eq(val, "385d6518-fb73-45fc-b649-0527d8576130"); jwt_free(jwt); ret = jwt_new(&jwt); ck_assert_int_eq(ret, 0); ck_assert(jwt != NULL); ret = jwt_add_grants_json(jwt, json2); ck_assert_int_eq(ret, 0); js_val = jwt_get_grant_obj (jwt, "nbf"); ck_assert (js_val != NULL); ck_assert (json_is_integer (js_val)); ck_assert (json_integer_value (js_val) == 12345678); ret = jwt_get_grant_int_or_str (jwt, "nbf", &val, &intval); ck_assert_int_eq(ret, 0); ck_assert(val == NULL); ck_assert (intval == 12345678); }
END_TEST START_TEST(test_jwt_encode_invalid) { unsigned char key512[64] = "012345678901234567890123456789XY" "012345678901234567890123456789XY"; jwt_t *jwt = NULL; int ret = 0; ALLOC_JWT(&jwt); ret = jwt_add_grant(jwt, "iss", "files.cyphre.com"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "sub", "user0"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "ref", "XXXX-YYYY-ZZZZ-AAAA-CCCC"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant_int(jwt, "iat", TS_CONST); ck_assert_int_eq(ret, 0); ret = jwt_set_alg(jwt, JWT_ALG_HS512, NULL, 0); ck_assert_int_eq(ret, EINVAL); ret = jwt_set_alg(jwt, JWT_ALG_HS512, NULL, sizeof(key512)); ck_assert_int_eq(ret, EINVAL); ret = jwt_set_alg(jwt, JWT_ALG_HS512, key512, 0); ck_assert_int_eq(ret, EINVAL); ret = jwt_set_alg(jwt, JWT_ALG_NONE, key512, sizeof(key512)); ck_assert_int_eq(ret, EINVAL); ret = jwt_set_alg(jwt, JWT_ALG_NONE, key512, 0); ck_assert_int_eq(ret, EINVAL); ret = jwt_set_alg(jwt, JWT_ALG_NONE, NULL, sizeof(key512)); ck_assert_int_eq(ret, EINVAL); /* Set a value that will never happen. */ ret = jwt_set_alg(jwt, 999, NULL, 0); ck_assert_int_eq(ret, EINVAL); jwt_free(jwt); }
END_TEST START_TEST(test_jwt_encode_hs512) { const char res[] = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpYXQiOj" "E0NzU5ODA1NDUsImlzcyI6ImZpbGVzLmN5cGhyZS5jb20iLCJyZWYiOiJY" "WFhYLVlZWVktWlpaWi1BQUFBLUNDQ0MiLCJzdWIiOiJ1c2VyMCJ9.EETPP" "pt4ViWccjHExKKyS-WPVtsvFTMVCl3WniLGdw_ZwGwXAEZ5ujf4cjmt1DU" "akpemETBfFDEFsKaFA7ApjA"; unsigned char key512[64] = "012345678901234567890123456789XY" "012345678901234567890123456789XY"; jwt_t *jwt = NULL; int ret = 0; char *out; ALLOC_JWT(&jwt); ret = jwt_add_grant(jwt, "iss", "files.cyphre.com"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "sub", "user0"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "ref", "XXXX-YYYY-ZZZZ-AAAA-CCCC"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant_int(jwt, "iat", TS_CONST); ck_assert_int_eq(ret, 0); ret = jwt_set_alg(jwt, JWT_ALG_HS512, key512, sizeof(key512)); ck_assert_int_eq(ret, 0); out = jwt_encode_str(jwt); ck_assert_ptr_ne(out, NULL); ck_assert_str_eq(out, res); free(out); jwt_free(jwt); }
END_TEST START_TEST(test_jwt_encode_hs384) { const char res[] = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzM4NCJ9.eyJpYXQi" "OjE0NzU5ODA1NDUsImlzcyI6ImZpbGVzLmN5cGhyZS5jb20iLCJyZWYi" "OiJYWFhYLVlZWVktWlpaWi1BQUFBLUNDQ0MiLCJzdWIiOiJ1c2VyMCJ9" ".Iu3GemfZo8eJX78QtgNXgYvb0KLo8_TsZskjivx8tc4jJ1-KhFpDtOr" "W4KYBFspI"; unsigned char key384[48] = "aaaabbbbccccddddeeeeffffgggghhhh" "iiiijjjjkkkkllll"; jwt_t *jwt = NULL; int ret = 0; char *out; ALLOC_JWT(&jwt); ret = jwt_add_grant(jwt, "iss", "files.cyphre.com"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "sub", "user0"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "ref", "XXXX-YYYY-ZZZZ-AAAA-CCCC"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant_int(jwt, "iat", TS_CONST); ck_assert_int_eq(ret, 0); ret = jwt_set_alg(jwt, JWT_ALG_HS384, key384, sizeof(key384)); ck_assert_int_eq(ret, 0); out = jwt_encode_str(jwt); ck_assert_ptr_ne(out, NULL); ck_assert_str_eq(out, res); free(out); jwt_free(jwt); }
END_TEST START_TEST(test_jwt_encode_hs256) { const char res[] = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE0NzU" "5ODA1NDUsImlzcyI6ImZpbGVzLmN5cGhyZS5jb20iLCJyZWYiOiJYWFhYLVlZWV" "ktWlpaWi1BQUFBLUNDQ0MiLCJzdWIiOiJ1c2VyMCJ9.ldP-njT746Qv9MihQmuy" "_CgNg64lKywpBgkDxkkfkAs"; unsigned char key256[32] = "012345678901234567890123456789XY"; jwt_t *jwt = NULL; int ret = 0; char *out; ALLOC_JWT(&jwt); ret = jwt_add_grant(jwt, "iss", "files.cyphre.com"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "sub", "user0"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant(jwt, "ref", "XXXX-YYYY-ZZZZ-AAAA-CCCC"); ck_assert_int_eq(ret, 0); ret = jwt_add_grant_int(jwt, "iat", TS_CONST); ck_assert_int_eq(ret, 0); ret = jwt_set_alg(jwt, JWT_ALG_HS256, key256, sizeof(key256)); ck_assert_int_eq(ret, 0); out = jwt_encode_str(jwt); ck_assert_ptr_ne(out, NULL); ck_assert_str_eq(out, res); free(out); jwt_free(jwt); }
END_TEST START_TEST(test_jwt_grant_invalid) { jwt_t *jwt = NULL; const char *val; int ret = 0; ret = jwt_new(&jwt); ck_assert_int_eq(ret, 0); ck_assert(jwt != NULL); ret = jwt_add_grant(jwt, "iss", NULL); ck_assert_int_eq(ret, EINVAL); ret = jwt_del_grant(jwt, ""); ck_assert_int_eq(ret, EINVAL); val = jwt_get_grant(jwt, NULL); ck_assert_int_eq(errno, EINVAL); ck_assert(val == NULL); jwt_free(jwt); }
int mosquitto_auth_unpwd_check(void *user_data, const char *username, const char *password) { jwt_t *jwt; #ifdef MQAP_DEBUG const char* val; int i_val; #endif time_t now; int iat; int exp; unsigned char key[32] = "012345678901234567890123456789AB"; if (username == NULL || password == NULL) { return MOSQ_ERR_AUTH; } #ifdef MQAP_DEBUG fprintf(stderr, "mosquitto_auth_unpwd_check: username=%s, password=%s\n", username, password); #endif if ( ! strcmp(username, "jwt") ) { time(&now); int status = jwt_decode(&jwt, password, key , sizeof(key)); if (( status == 0 ) && (jwt != NULL) ) { #ifdef MQAP_DEBUG fprintf(stderr, "mosquitto_auth_unpwd_check: password is a valid JWT token\n"); val = jwt_get_grant(jwt, "iss"); fprintf(stderr, "mosquitto_auth_unpwd_check: iss : %s\n", val); val = jwt_get_grant(jwt, "sub"); fprintf(stderr, "mosquitto_auth_unpwd_check: sub : %s\n", val); i_val = get_js_int(jwt->grants, "iat"); fprintf(stderr, "mosquitto_auth_unpwd_check: iat : %d\n", i_val); i_val = get_js_int(jwt->grants, "exp"); fprintf(stderr, "mosquitto_auth_unpwd_check: exp : %d\n", i_val); val = get_js_object(jwt->grants, "aud"); fprintf(stderr, "mosquitto_auth_unpwd_check: aud : %s\n", val); fprintf(stderr, "mosquitto_auth_unpwd_check: now : %d\n", (int)now); #endif iat = get_js_int(jwt->grants, "iat"); exp = get_js_int(jwt->grants, "exp"); if ( (now < iat) || (now > exp) ) { #ifdef MQAP_DEBUG fprintf(stderr, "mosquitto_auth_unpwd_check: token is expired\n"); #endif jwt_free(jwt); return MOSQ_ERR_AUTH; } // TODO add here some other controls about iss, sub, ... jwt_free(jwt); return MOSQ_ERR_SUCCESS; } else { #ifdef MQAP_DEBUG fprintf(stderr, "mosquitto_auth_unpwd_check: password is not a valid token %d\n", status); #endif } } return MOSQ_ERR_AUTH; }