gss-token: restructure and refactor the code a bit.

This commit is contained in:
Roland C. Dowdeswell
2020-10-07 15:51:39 +01:00
parent ca59ee0ddd
commit 9693bdb272
2 changed files with 130 additions and 111 deletions

View File

@@ -20,7 +20,9 @@
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
generates and consumes base64 encoded GSS tokens. 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 .Pp
.Nm .Nm
supports the following options: supports the following options:
@@ -54,22 +56,22 @@ to generated tokens and expect it on consumed tokens.
repeat the operation repeat the operation
.Ar count .Ar count
times. times.
This flag only changes the behaviour when operating in initiator mode.
This is good for very basic benchmarking. This is good for very basic benchmarking.
.It Fl l .It Fl l
loop infinitely in read mode. loop indefinitely in acceptor mode.
This is to support a multiple round trip GSS mechanism.
.It Fl n .It Fl n
do not output the generated token. do not output the generated tokens.
.It Fl r .It Fl r
read a token rather than generate a token. run in acceptor mode.
.El .El
.Pp .Pp
.Nm .Nm
takes one argument, a takes one argument, a
.Ar host@service .Ar host@service
specifier. specifier.
The argument is required when generating a token but is optional if The argument is required when running as an initiator but is optional as
consuming (reading) a token. an acceptor.
.Sh SEE ALSO .Sh SEE ALSO
.Xr gssapi 3 , .Xr gssapi 3 ,
.Xr kerberos 8 . .Xr kerberos 8 .

View File

@@ -164,8 +164,118 @@ gss_mk_err(OM_uint32 maj_stat, OM_uint32 min_stat, const char *preamble)
return str; 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 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_ctx_id_t ctx = GSS_C_NO_CONTEXT;
gss_buffer_desc in; gss_buffer_desc in;
@@ -174,7 +284,6 @@ write_one_token(gss_name_t service, int delegate, int negotiate)
OM_uint32 min; OM_uint32 min;
OM_uint32 flags = 0; OM_uint32 flags = 0;
int ret = 0; int ret = 0;
char *base64_output = NULL;
in.length = 0; in.length = 0;
in.value = 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); GBAIL("gss_init_sec_context", maj, min);
if (rk_base64_encode(out.value, out.length, &base64_output) < 0) { write_token(&out, negotiate);
fprintf(stderr, "Out of memory.\n");
ret = 1;
goto bail;
}
if (!nflag)
printf("%s%s\n", negotiate?"Negotiate ":"", base64_output);
bail: bail:
if (out.value) if (out.value)
@@ -212,8 +314,6 @@ bail:
gss_delete_sec_context(&min, &ctx, NULL); gss_delete_sec_context(&min, &ctx, NULL);
} }
free(base64_output);
return ret; return ret;
} }
@@ -250,7 +350,7 @@ copy_cache(krb5_context kctx, krb5_ccache from, krb5_ccache to)
} }
static int static int
write_token(gss_name_t service, int delegate, int negotiate, int memcache, initiate_many(gss_name_t service, int delegate, int negotiate, int memcache,
size_t count) size_t count)
{ {
krb5_error_code kret; krb5_error_code kret;
@@ -269,7 +369,7 @@ write_token(gss_name_t service, int delegate, int negotiate, int memcache,
for (i=0; i < count; i++) { for (i=0; i < count; i++) {
if (memcache) if (memcache)
K5BAIL(copy_cache(kctx, def_cache, mem_cache)); 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) if (!nflag && i < count - 1)
printf("\n"); printf("\n");
@@ -285,44 +385,8 @@ write_token(gss_name_t service, int delegate, int negotiate, int memcache,
return kret; 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 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 cred = NULL;
gss_cred_id_t deleg_creds = 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_ccache ccache = NULL;
krb5_error_code kret; krb5_error_code kret;
OM_uint32 maj, min; OM_uint32 maj, min;
size_t len;
char *inbuf = NULL;
char *tmp;
int ret = 0; int ret = 0;
if (service) { if (service) {
@@ -346,39 +407,9 @@ read_one_token(gss_name_t service, const char *ccname, int negotiate)
GBAIL("gss_acquire_cred", maj, min); GBAIL("gss_acquire_cred", maj, min);
} }
inbuf = read_buffer(stdin); ret = read_token(&in, negotiate);
if (!inbuf) if (ret)
/* Just a couple of \n's in a row or EOF, not an error. */ return ret;
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;
out.length = 0; out.length = 0;
out.value = 0; out.value = 0;
@@ -438,20 +469,6 @@ bail:
gss_release_cred(&min, &deleg_creds); gss_release_cred(&min, &deleg_creds);
free(in.value); 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; return ret;
} }
@@ -545,7 +562,7 @@ main(int argc, char **argv)
"make sense without -r.\n"); "make sense without -r.\n");
usage(1); usage(1);
} }
ret = write_token(service, Dflag, Nflag, Mflag, count); ret = initiate_many(service, Dflag, Nflag, Mflag, count);
goto done; goto done;
} }
@@ -556,7 +573,7 @@ main(int argc, char **argv)
} }
do { do {
ret = read_token(service, ccname, Nflag, count); ret = accept_one(service, ccname, Nflag);
} while (lflag && !ret && !feof(stdin)); } while (lflag && !ret && !feof(stdin));
done: done: