From 9693bdb2727490cee8a8ebf3243d9a4e46d61658 Mon Sep 17 00:00:00 2001 From: "Roland C. Dowdeswell" Date: Wed, 7 Oct 2020 15:51:39 +0100 Subject: [PATCH] gss-token: restructure and refactor the code a bit. --- lib/gssapi/gss-token.1 | 16 +-- lib/gssapi/gss-token.c | 225 ++++++++++++++++++++++------------------- 2 files changed, 130 insertions(+), 111 deletions(-) diff --git a/lib/gssapi/gss-token.1 b/lib/gssapi/gss-token.1 index 431cd94ff..7e16af0ac 100644 --- a/lib/gssapi/gss-token.1 +++ b/lib/gssapi/gss-token.1 @@ -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 . diff --git a/lib/gssapi/gss-token.c b/lib/gssapi/gss-token.c index 644988073..ee4ad7e92 100644 --- a/lib/gssapi/gss-token.c +++ b/lib/gssapi/gss-token.c @@ -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: