1 /* Copyright (C) 2019 Jeremy Thien <jeremy.thien@gmail.com>
2    This file is part of the JWT C Library
3 
4    This Source Code Form is subject to the terms of the Mozilla Public
5    License, v. 2.0. If a copy of the MPL was not distributed with this
6    file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <jwt.h>
11 #include <getopt.h>
12 #include <string.h>
13 #include <time.h>
14 #include <string.h>
15 #include <libgen.h>
16 
usage(const char * name)17 void usage(const char *name)
18 {
19 	printf("%s OPTIONS\n", name);
20 	printf("Options:\n"
21 			"  -k --key KEY  The private key to use for signing\n"
22 			"  -a --alg ALG  The algorithm to use for signing\n"
23 			"  -c --claim KEY=VALUE  A claim to add to JWT\n"
24 			"  -j --json '{key1:value1}'  A json to add to JWT\n"
25 			);
26 	exit(0);
27 }
28 
main(int argc,char * argv[])29 int main(int argc, char *argv[])
30 {
31 	char opt_key_name[200] = "test-rsa256.pem";
32 	jwt_alg_t opt_alg = JWT_ALG_RS256;
33 	time_t iat = time(NULL);
34 
35 	int oc = 0;
36 	char *optstr = "hk:a:c:j:";
37 	struct option opttbl[] = {
38 		{ "help",         no_argument,        NULL, 'h'         },
39 		{ "key",          required_argument,  NULL, 'k'         },
40 		{ "alg",          required_argument,  NULL, 'a'         },
41 		{ "claim",        required_argument,  NULL, 'c'         },
42 		{ "json",         required_argument,  NULL, 'j'         },
43 		{ NULL, 0, 0, 0 },
44 	};
45 
46 	char *k = NULL, *v = NULL;
47 	int claims_count = 0;
48 	int i = 0;
49 	unsigned char key[10240];
50 	size_t key_len = 0;
51 	FILE *fp_priv_key;
52 	int ret = 0;
53 	jwt_t *jwt;
54 	struct kv {
55 		char *key;
56 		char *val;
57 	} opt_claims[100];
58 	memset(opt_claims, 0, sizeof(opt_claims));
59 	char* opt_json = NULL;
60 
61 	while ((oc = getopt_long(argc, argv, optstr, opttbl, NULL)) != -1) {
62 		switch (oc) {
63 		case 'k':
64 			strncpy(opt_key_name, optarg, sizeof(opt_key_name));
65 			opt_key_name[sizeof(opt_key_name) - 1] = '\0';
66 			break;
67 
68 		case 'a':
69 			opt_alg = jwt_str_alg(optarg);
70 			if (opt_alg == JWT_ALG_INVAL) {
71 				fprintf(stderr, "%s is not supported algorithm, using RS256\n", optarg);
72 				opt_alg = JWT_ALG_RS256;
73 			}
74 			break;
75 
76 		case 'c':
77 			k = strtok(optarg, "=");
78 			if (k) {
79 				v = strtok(NULL, "=");
80 				if (v) {
81 					opt_claims[claims_count].key = strdup(k);
82 					opt_claims[claims_count].val = strdup(v);
83 					claims_count++;
84 				}
85 			}
86 			break;
87 		case 'j':
88 			if (optarg != NULL) {
89 				opt_json = strdup(optarg);
90 			}
91 			break;
92 
93 		case 'h':
94 			usage(basename(argv[0]));
95 			return 0;
96 
97 		default: /* '?' */
98 			usage(basename(argv[0]));
99 			exit(EXIT_FAILURE);
100 		}
101 	}
102 
103 	fprintf(stderr, "jwtgen: privkey %s algorithm %s\n",
104 			opt_key_name, jwt_alg_str(opt_alg));
105 
106 	if (opt_alg > JWT_ALG_NONE) {
107 		fp_priv_key = fopen(opt_key_name, "r");
108 		key_len = fread(key, 1, sizeof(key), fp_priv_key);
109 		fclose(fp_priv_key);
110 		key[key_len] = '\0';
111 		fprintf(stderr, "priv key loaded %s (%zu)!\n", opt_key_name, key_len);
112 	}
113 
114 	ret = jwt_new(&jwt);
115 	if (ret != 0 || jwt == NULL) {
116 		fprintf(stderr, "invalid jwt\n");
117 		goto finish;
118 	}
119 
120 	ret = jwt_add_grant_int(jwt, "iat", iat);
121 	for (i = 0; i < claims_count; i++) {
122 		fprintf(stderr, "Adding claim %s with valu %s\n", opt_claims[i].key, opt_claims[i].val);
123 		jwt_add_grant(jwt, opt_claims[i].key, opt_claims[i].val);
124 	}
125 
126 	if (opt_json != NULL) {
127 		ret = jwt_add_grants_json(jwt, opt_json);
128 		if (ret != 0) {
129 			fprintf(stderr, "Input json is invalid\n");
130 			goto finish;
131 		}
132 	}
133 
134 	ret = jwt_set_alg(jwt, opt_alg, opt_alg == JWT_ALG_NONE ? NULL : key, opt_alg == JWT_ALG_NONE ? 0 : key_len);
135 	if (ret < 0) {
136 		fprintf(stderr, "jwt incorrect algorithm\n");
137 		goto finish;
138 	}
139 
140 	jwt_dump_fp(jwt, stderr, 1);
141 
142 	fprintf(stderr, "jwt algo %s!\n", jwt_alg_str(opt_alg));
143 
144 	char *out = jwt_encode_str(jwt);
145 	printf("%s\n", out);
146 
147 	jwt_free_str(out);
148 finish:
149 	if (opt_json != NULL) {
150 		free(opt_json);
151 	}
152 	jwt_free(jwt);
153 
154 	return 0;
155 }
156 
157