Przeglądaj źródła

jwt: added caching support for private/public keys

- done if key_mode=1, on first use of the key
Daniel-Constantin Mierla 4 lat temu
rodzic
commit
283e36601c
1 zmienionych plików z 96 dodań i 24 usunięć
  1. 96 24
      src/modules/jwt/jwt_mod.c

+ 96 - 24
src/modules/jwt/jwt_mod.c

@@ -50,6 +50,14 @@ static int _jwt_key_mode = 0;
 static str _jwt_result = STR_NULL;
 static unsigned int _jwt_verify_status = 0;
 
+typedef struct jwt_fcache {
+	str fname;
+	str fdata;
+	struct jwt_fcache *next;
+} jwt_fcache_t;
+
+static jwt_fcache_t *_jwt_fcache_list = NULL;
+
 static cmd_export_t cmds[]={
 	{"jwt_generate", (cmd_function)w_jwt_generate, 3,
 		fixup_spve_all, 0, ANY_ROUTE},
@@ -110,6 +118,56 @@ static void mod_destroy(void)
 	return;
 }
 
+/**
+ *
+ */
+static int jwt_fcache_get(str *key, str *kdata)
+{
+	jwt_fcache_t *fc = NULL;
+
+	if(_jwt_key_mode!=1) {
+		return -1;
+	}
+	for(fc=_jwt_fcache_list; fc!=NULL; fc=fc->next) {
+		if(fc->fname.len==key->len
+				&& strncmp(fc->fname.s, key->s, key->len)==0) {
+			LM_DBG("file found in cache: %.*s\n", key->len, key->s);
+			*kdata = fc->fdata;
+			break;
+		}
+	}
+	return 0;
+}
+
+/**
+ *
+ */
+static int jwt_fcache_add(str *key, str *kdata)
+{
+	jwt_fcache_t *fc = NULL;
+
+	if(_jwt_key_mode!=1) {
+		return -1;
+	}
+	fc = (jwt_fcache_t*)pkg_malloc(sizeof(jwt_fcache_t) + key->len
+			+ kdata->len + 2);
+	if(fc==NULL) {
+		PKG_MEM_ERROR;
+		return -1;
+	}
+	memset(fc, 0, sizeof(jwt_fcache_t) + key->len + kdata->len + 2);
+	fc->fname.s = (char*)fc + sizeof(jwt_fcache_t);
+	fc->fname.len = key->len;
+	memcpy(fc->fname.s, key->s, key->len);
+	fc->fdata.s = fc->fname.s + fc->fname.len + 1;
+	fc->fdata.len = kdata->len;
+	memcpy(fc->fdata.s, kdata->s, kdata->len);
+	fc->next = _jwt_fcache_list;
+	_jwt_fcache_list = fc;
+
+	return 0;
+}
+
 /**
  *
  */
@@ -117,6 +175,7 @@ static int ki_jwt_generate(sip_msg_t* msg, str *key, str *alg, str *claims)
 {
 	str dupclaims = STR_NULL;
 	str sparams = STR_NULL;
+	str kdata = STR_NULL;
 	jwt_alg_t valg = JWT_ALG_NONE;
 	time_t iat;
 	FILE *fpk = NULL;
@@ -147,18 +206,24 @@ static int ki_jwt_generate(sip_msg_t* msg, str *key, str *alg, str *claims)
 		LM_ERR("failed to duplicate claims\n");
 		return -1;
 	}
-	fpk= fopen(key->s, "r");
-	if(fpk==NULL) {
-		LM_ERR("failed to read key file: %s\n", key->s);
-		goto error;
-	}
-	keybuf_len = fread(keybuf, 1, sizeof(keybuf), fpk);
-	fclose(fpk);
-	if(keybuf_len==0) {
-		LM_ERR("unable to read key file content: %s\n", key->s);
-		goto error;
+	jwt_fcache_get(key, &kdata);
+	if(kdata.s==NULL) {
+		fpk= fopen(key->s, "r");
+		if(fpk==NULL) {
+			LM_ERR("failed to read key file: %s\n", key->s);
+			goto error;
+		}
+		keybuf_len = fread(keybuf, 1, sizeof(keybuf), fpk);
+		fclose(fpk);
+		if(keybuf_len==0) {
+			LM_ERR("unable to read key file content: %s\n", key->s);
+			goto error;
+		}
+		keybuf[keybuf_len] = '\0';
+		kdata.s = (char*)keybuf;
+		kdata.len = (int)keybuf_len;
+		jwt_fcache_add(key, &kdata);
 	}
-	keybuf[keybuf_len] = '\0';
 	sparams = dupclaims;
 	if(sparams.s[sparams.len-1]==';') {
 		sparams.len--;
@@ -185,7 +250,7 @@ static int ki_jwt_generate(sip_msg_t* msg, str *key, str *alg, str *claims)
 		}
 	}
 
-	ret = jwt_set_alg(jwt, valg, keybuf, keybuf_len);
+	ret = jwt_set_alg(jwt, valg, (unsigned char*)kdata.s, (size_t)kdata.len);
 	if (ret < 0) {
 		LM_ERR("failed to set algorithm and key\n");
 		goto error;
@@ -247,6 +312,7 @@ static int ki_jwt_verify(sip_msg_t* msg, str *key, str *alg, str *claims,
 {
 	str dupclaims = STR_NULL;
 	jwt_alg_t valg = JWT_ALG_NONE;
+	str kdata = STR_NULL;
 	time_t iat;
 	FILE *fpk = NULL;
 	unsigned char keybuf[10240];
@@ -277,18 +343,24 @@ static int ki_jwt_verify(sip_msg_t* msg, str *key, str *alg, str *claims,
 		LM_ERR("failed to duplicate claims\n");
 		return -1;
 	}
-	fpk= fopen(key->s, "r");
-	if(fpk==NULL) {
-		LM_ERR("failed to read key file: %s\n", key->s);
-		goto error;
-	}
-	keybuf_len = fread(keybuf, 1, sizeof(keybuf), fpk);
-	fclose(fpk);
-	if(keybuf_len==0) {
-		LM_ERR("unable to read key file content: %s\n", key->s);
-		goto error;
+	jwt_fcache_get(key, &kdata);
+	if(kdata.s==NULL) {
+		fpk= fopen(key->s, "r");
+		if(fpk==NULL) {
+			LM_ERR("failed to read key file: %s\n", key->s);
+			goto error;
+		}
+		keybuf_len = fread(keybuf, 1, sizeof(keybuf), fpk);
+		fclose(fpk);
+		if(keybuf_len==0) {
+			LM_ERR("unable to read key file content: %s\n", key->s);
+			goto error;
+		}
+		keybuf[keybuf_len] = '\0';
+		kdata.s = (char*)keybuf;
+		kdata.len = (int)keybuf_len;
+		jwt_fcache_add(key, &kdata);
 	}
-	keybuf[keybuf_len] = '\0';
 	sparams = dupclaims;
 	if(sparams.s[sparams.len-1]==';') {
 		sparams.len--;
@@ -316,7 +388,7 @@ static int ki_jwt_verify(sip_msg_t* msg, str *key, str *alg, str *claims,
 		}
 	}
 
-	ret = jwt_decode(&jwt, jwtval->s, keybuf, keybuf_len);
+	ret = jwt_decode(&jwt, jwtval->s, (unsigned char*)kdata.s, (size_t)kdata.len);
 	if (ret!=0 || jwt==NULL) {
 		LM_ERR("failed to decode jwt value\n");
 		goto error;