gss-token: restructure and refactor the code a bit.
This commit is contained in:
		| @@ -20,7 +20,9 @@ | ||||
| .Sh DESCRIPTION | ||||
| .Nm | ||||
| generates and consumes base64 encoded GSS tokens. | ||||
| It is mostly useful for testing. | ||||
| By default, it runs as an initiator and with the | ||||
| .Fl r | ||||
| flag it becomes an acceptor. | ||||
| .Pp | ||||
| .Nm | ||||
| supports the following options: | ||||
| @@ -54,22 +56,22 @@ to generated tokens and expect it on consumed tokens. | ||||
| repeat the operation | ||||
| .Ar count | ||||
| times. | ||||
| This flag only changes the behaviour when operating in initiator mode. | ||||
| This is good for very basic benchmarking. | ||||
| .It Fl l | ||||
| loop infinitely in read mode. | ||||
| This is to support a multiple round trip GSS mechanism. | ||||
| loop indefinitely in acceptor mode. | ||||
| .It Fl n | ||||
| do not output the generated token. | ||||
| do not output the generated tokens. | ||||
| .It Fl r | ||||
| read a token rather than generate a token. | ||||
| run in acceptor mode. | ||||
| .El | ||||
| .Pp | ||||
| .Nm | ||||
| takes one argument, a | ||||
| .Ar host@service | ||||
| specifier. | ||||
| The argument is required when generating a token but is optional if | ||||
| consuming (reading) a token. | ||||
| The argument is required when running as an initiator but is optional as | ||||
| an acceptor. | ||||
| .Sh SEE ALSO | ||||
| .Xr gssapi 3 , | ||||
| .Xr kerberos 8 . | ||||
|   | ||||
| @@ -164,8 +164,118 @@ gss_mk_err(OM_uint32 maj_stat, OM_uint32 min_stat, const char *preamble) | ||||
| 	return str; | ||||
| } | ||||
|  | ||||
| static char * | ||||
| read_buffer(FILE *fp) | ||||
| { | ||||
| 	char	 buf[65536]; | ||||
| 	char	*p; | ||||
| 	char	*ret = NULL; | ||||
| 	size_t	 buflen; | ||||
| 	size_t	 retlen = 0; | ||||
|  | ||||
| 	while (fgets(buf, sizeof(buf), fp) != NULL) { | ||||
| 		if ((p = strchr(buf, '\n')) == NULL) { | ||||
| 			fprintf(stderr, "Long line, exiting.\n"); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 		*p = '\0'; | ||||
| 		buflen = strlen(buf); | ||||
| 		if (buflen == 0) | ||||
| 			break; | ||||
|  | ||||
| 		ret = realloc(ret, retlen + buflen + 1); | ||||
| 		if (!ret) { | ||||
| 			perror("realloc"); | ||||
| 			exit(1); | ||||
| 		} | ||||
| 		memcpy(ret + retlen, buf, buflen); | ||||
| 		ret[retlen + buflen] = '\0'; | ||||
| 		retlen += buflen; | ||||
| 	} | ||||
|  | ||||
| 	if (ferror(stdin)) { | ||||
| 		perror("fgets"); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int | ||||
| write_one_token(gss_name_t service, int delegate, int negotiate) | ||||
| write_token(gss_buffer_t out, int negotiate) | ||||
| { | ||||
| 	char	*outstr = NULL; | ||||
| 	char	*p = out->value; | ||||
| 	size_t	 len = out->length; | ||||
| 	int	 ret; | ||||
|  | ||||
| 	if (nflag) | ||||
| 		return 0; | ||||
|  | ||||
| 	ret = rk_base64_encode(p, len, &outstr); | ||||
| 	if (ret < 0) { | ||||
| 		fprintf(stderr, "Out of memory.\n"); | ||||
| 		return 1; | ||||
| 	} | ||||
| 	printf("%s%s\n", negotiate?"Negotiate ":"", outstr); | ||||
| 	free(outstr); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| read_token(gss_buffer_t in, int negotiate) | ||||
| { | ||||
| 	char	*inbuf = NULL; | ||||
| 	char	*tmp; | ||||
| 	size_t	 len; | ||||
| 	int	 ret = 0; | ||||
|  | ||||
| 	inbuf = read_buffer(stdin); | ||||
| 	if (!inbuf) | ||||
| 		/* Just a couple of \n's in a row or EOF, no error. */ | ||||
| 		return 0; | ||||
|  | ||||
| 	tmp = inbuf; | ||||
| 	if (negotiate) { | ||||
| 		if (strncasecmp("Negotiate ", inbuf, 10)) { | ||||
| 			fprintf(stderr, "Token doesn't begin with " | ||||
| 			    "\"Negotiate \"\n"); | ||||
| 			ret = -1; | ||||
| 			goto bail; | ||||
| 		} | ||||
|  | ||||
| 		tmp += 10; | ||||
| 	} | ||||
|  | ||||
| 	len = strlen(tmp); | ||||
| 	in->value = malloc(len + 1); | ||||
| 	if (!in->value) { | ||||
| 		fprintf(stderr, "Out of memory.\n"); | ||||
| 		ret = -1; | ||||
| 		goto bail; | ||||
| 	} | ||||
| 	ret = rk_base64_decode(tmp, in->value); | ||||
| 	if (ret < 0) { | ||||
| 		free(in->value); | ||||
| 		in->value = NULL; | ||||
| 		if (errno == EOVERFLOW) | ||||
| 			fprintf(stderr, "Token is too big\n"); | ||||
| 		else | ||||
| 			fprintf(stderr, "Token encoding is not valid " | ||||
| 			    "base64\n"); | ||||
| 		goto bail; | ||||
| 	} else { | ||||
| 		in->length = ret; | ||||
| 	} | ||||
| 	ret = 0; | ||||
|  | ||||
| bail: | ||||
| 	free(inbuf); | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int | ||||
| initiate_one(gss_name_t service, int delegate, int negotiate) | ||||
| { | ||||
| 	gss_ctx_id_t	 ctx = GSS_C_NO_CONTEXT; | ||||
| 	gss_buffer_desc	 in; | ||||
| @@ -174,7 +284,6 @@ write_one_token(gss_name_t service, int delegate, int negotiate) | ||||
| 	OM_uint32	 min; | ||||
| 	OM_uint32	 flags = 0; | ||||
| 	int		 ret = 0; | ||||
| 	char		*base64_output = NULL; | ||||
|  | ||||
| 	in.length  = 0; | ||||
| 	in.value   = 0; | ||||
| @@ -190,14 +299,7 @@ write_one_token(gss_name_t service, int delegate, int negotiate) | ||||
|  | ||||
| 	GBAIL("gss_init_sec_context", maj, min); | ||||
|  | ||||
| 	if (rk_base64_encode(out.value, out.length, &base64_output) < 0) { | ||||
| 		fprintf(stderr, "Out of memory.\n"); | ||||
| 		ret = 1; | ||||
| 		goto bail; | ||||
| 	} | ||||
|  | ||||
| 	if (!nflag) | ||||
| 		printf("%s%s\n", negotiate?"Negotiate ":"", base64_output); | ||||
| 	write_token(&out, negotiate); | ||||
|  | ||||
| bail: | ||||
| 	if (out.value) | ||||
| @@ -212,8 +314,6 @@ bail: | ||||
| 		gss_delete_sec_context(&min, &ctx, NULL); | ||||
| 	} | ||||
|  | ||||
| 	free(base64_output); | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| @@ -250,8 +350,8 @@ copy_cache(krb5_context kctx, krb5_ccache from, krb5_ccache to) | ||||
| } | ||||
|  | ||||
| static int | ||||
| write_token(gss_name_t service, int delegate, int negotiate, int memcache, | ||||
| 	    size_t count) | ||||
| initiate_many(gss_name_t service, int delegate, int negotiate, int memcache, | ||||
| 	      size_t count) | ||||
| { | ||||
| 	krb5_error_code	kret; | ||||
| 	krb5_context	kctx = NULL; | ||||
| @@ -269,7 +369,7 @@ write_token(gss_name_t service, int delegate, int negotiate, int memcache, | ||||
| 	for (i=0; i < count; i++) { | ||||
| 		if (memcache) | ||||
| 			K5BAIL(copy_cache(kctx, def_cache, mem_cache)); | ||||
| 		kret = write_one_token(service, delegate, negotiate); | ||||
| 		kret = initiate_one(service, delegate, negotiate); | ||||
|  | ||||
| 		if (!nflag && i < count - 1) | ||||
| 			printf("\n"); | ||||
| @@ -285,44 +385,8 @@ write_token(gss_name_t service, int delegate, int negotiate, int memcache, | ||||
| 	return kret; | ||||
| } | ||||
|  | ||||
| static char * | ||||
| read_buffer(FILE *fp) | ||||
| { | ||||
| 	char	 buf[65536]; | ||||
| 	char	*p; | ||||
| 	char	*ret = NULL; | ||||
| 	size_t	 buflen; | ||||
| 	size_t	 retlen = 0; | ||||
|  | ||||
| 	while (fgets(buf, sizeof(buf), fp) != NULL) { | ||||
| 		if ((p = strchr(buf, '\n')) == NULL) { | ||||
| 			fprintf(stderr, "Long line, exiting.\n"); | ||||
| 			exit(1); | ||||
| 		} | ||||
|  | ||||
| 		*p = '\0'; | ||||
|  | ||||
| 		buflen = strlen(buf); | ||||
|  | ||||
| 		if (buflen == 0) | ||||
| 			break; | ||||
|  | ||||
| 		ret = realloc(ret, retlen + buflen + 1); | ||||
|  | ||||
| 		memcpy(ret + retlen, buf, buflen); | ||||
| 		ret[retlen + buflen] = '\0'; | ||||
| 	} | ||||
|  | ||||
| 	if (ferror(stdin)) { | ||||
| 		perror("fgets"); | ||||
| 		exit(1); | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int | ||||
| read_one_token(gss_name_t service, const char *ccname, int negotiate) | ||||
| accept_one(gss_name_t service, const char *ccname, int negotiate) | ||||
| { | ||||
| 	gss_cred_id_t	 cred = NULL; | ||||
| 	gss_cred_id_t	 deleg_creds = NULL; | ||||
| @@ -335,9 +399,6 @@ read_one_token(gss_name_t service, const char *ccname, int negotiate) | ||||
| 	krb5_ccache	 ccache = NULL; | ||||
| 	krb5_error_code	 kret; | ||||
|         OM_uint32        maj, min; | ||||
| 	size_t		 len; | ||||
| 	char		*inbuf = NULL; | ||||
| 	char		*tmp; | ||||
| 	int		 ret = 0; | ||||
|  | ||||
| 	if (service) { | ||||
| @@ -346,39 +407,9 @@ read_one_token(gss_name_t service, const char *ccname, int negotiate) | ||||
| 		GBAIL("gss_acquire_cred", maj, min); | ||||
| 	} | ||||
|  | ||||
| 	inbuf = read_buffer(stdin); | ||||
| 	if (!inbuf) | ||||
| 		/* Just a couple of \n's in a row or EOF, not an error. */ | ||||
| 		return 0; | ||||
|  | ||||
| 	tmp = inbuf; | ||||
| 	if (negotiate) { | ||||
| 		if (strncasecmp("Negotiate ", inbuf, 10)) { | ||||
| 			fprintf(stderr, "Token doesn't begin with " | ||||
| 			    "\"Negotiate \"\n"); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		tmp += 10; | ||||
| 	} | ||||
|  | ||||
| 	len = strlen(tmp); | ||||
| 	in.value = malloc(len + 1); | ||||
| 	if (!in.value) { | ||||
| 		fprintf(stderr, "Out of memory.\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	ret = rk_base64_decode(tmp, in.value); | ||||
| 	if (ret < 0) { | ||||
| 		free(in.value); | ||||
| 		if (errno == EOVERFLOW) | ||||
| 			fprintf(stderr, "Token is too big\n"); | ||||
| 		else | ||||
| 			fprintf(stderr, "Token encoding is not valid base64\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
|         in.length = ret; | ||||
|         ret = 0; | ||||
| 	ret = read_token(&in, negotiate); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
|  | ||||
| 	out.length = 0; | ||||
| 	out.value  = 0; | ||||
| @@ -438,20 +469,6 @@ bail: | ||||
| 		gss_release_cred(&min, &deleg_creds); | ||||
|  | ||||
| 	free(in.value); | ||||
| 	free(inbuf); | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static int | ||||
| read_token(gss_name_t service, const char *ccname, int negotiate, size_t count) | ||||
| { | ||||
| 	size_t	i; | ||||
| 	int	ret; | ||||
|  | ||||
| 	for (i=0; i < count; i++) { | ||||
| 		ret = read_one_token(service, ccname, negotiate); | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
| @@ -545,7 +562,7 @@ main(int argc, char **argv) | ||||
| 			    "make sense without -r.\n"); | ||||
| 			usage(1); | ||||
| 		} | ||||
| 		ret = write_token(service, Dflag, Nflag, Mflag, count); | ||||
| 		ret = initiate_many(service, Dflag, Nflag, Mflag, count); | ||||
| 		goto done; | ||||
| 	} | ||||
|  | ||||
| @@ -556,7 +573,7 @@ main(int argc, char **argv) | ||||
| 	} | ||||
|  | ||||
| 	do { | ||||
| 		ret = read_token(service, ccname, Nflag, count); | ||||
| 		ret = accept_one(service, ccname, Nflag); | ||||
| 	} while (lflag && !ret && !feof(stdin)); | ||||
|  | ||||
| done: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Roland C. Dowdeswell
					Roland C. Dowdeswell