gss_OID * /* oid */
);
-#ifdef EXCESSIVE_LOGGING
-#define _log gssint_log
-#define _log_block gssint_log_block
-extern void _log(const char *, ...);
-extern void _log_block(const char *, int, const char *, void *, size_t);
-#define _log_block2(LABEL,PTR,SIZE) _log_block(__FILE__,__LINE__,LABEL,PTR,SIZE)
-#define SFILE (strrchr(__FILE__,'/') ? 1+strrchr(__FILE__,'/') : __FILE__)
-#else
-#define _log (void)
-#define _log_block(A,B,C,D,E) (void)(A,B,C,D,E)
-#define _log_block2(A,B,C) (void)(A,B,C)
-#define SFILE __FILE__
-#endif
-
#endif /* _GSSAPIP_GENERIC_H_ */
*vqueue = q;
return 0;
}
-
-/* debugging */
-
-#ifdef EXCESSIVE_LOGGING
-#include <stdio.h>
-#include <stdarg.h>
-#include <time.h>
-#define LOGPATH "/tmp/gsslog"
-void _log(const char *fmt, ...)
-{
-#if 0
- static FILE *logf;
- va_list x;
- if (logf == 0) {
- logf = fopen(LOGPATH, "a");
- if (logf)
- setvbuf(logf, 0, _IONBF, 0);
- }
- if (logf == 0)
- return;
- va_start(x, fmt);
- {
- struct timeval tv;
- struct tm tm;
- time_t tvsec;
- char buf[40];
- char *p;
-
- sprintf(buf,"[%d", getpid());
- p = buf + strlen(buf);
- gettimeofday(&tv, 0) == 0
- && (tvsec = tv.tv_sec)
- && strftime(p, buf + sizeof(buf) - p,
- ":%F-%T", localtime_r(&tvsec, &tm)) > 0
- && (p += strlen(p))
- && (buf + sizeof(buf) - p >= 10)
- && sprintf(p, ".%06ld", (long) tv.tv_usec);
- strcat(buf, "]");
- fprintf(logf, "%s", buf);
- }
- vfprintf(logf, fmt, x);
- va_end(x);
-#endif
-}
-#endif
gss_OID_desc toid;
int toksize = toksize_in;
- _log("%s:%d: %s(tok_type=0x%x, toksize=%d, wrapper_required=%d)\n",
- SFILE, __LINE__, __func__, tok_type, toksize, wrapper_required);
- _log_block2("input token", buf, toksize);
-
-#define LOG() _log("%s:%d: here\n", SFILE, __LINE__)
if ((toksize-=1) < 0)
return(G_BAD_TOK_HEADER);
if (*buf++ != 0x60) {
if ((seqsize = der_read_length(&buf, &toksize)) < 0)
return(G_BAD_TOK_HEADER);
- if (seqsize != toksize) {
- _log("%s:%d: bad token header: seqsize=%d toksize=%d\n",
- SFILE, __LINE__, seqsize, toksize);
+ if (seqsize != toksize)
return(G_BAD_TOK_HEADER);
- }
if ((toksize-=1) < 0)
return(G_BAD_TOK_HEADER);
return G_WRONG_MECH;
skip_wrapper:
if (tok_type != -1) {
- _log("%s:%d: toksize=%d\n", SFILE, __LINE__, toksize);
if ((toksize-=2) < 0)
return(G_BAD_TOK_HEADER);
- _log("%s:%d: buf@%p: %02x %02x\n", SFILE, __LINE__,
- buf, buf[0], buf[1]);
if ((*buf++ != ((tok_type>>8)&0xff)) ||
(*buf++ != (tok_type&0xff))) {
- _log("%s:%d: G_WRONG_TOKID: wanted 0x%x got 0x%x\n",
- SFILE, __LINE__, tok_type, buf[-2], buf[-1]);
return(G_WRONG_TOKID);
}
}
*buf_in = buf;
*body_size = toksize;
- _log("%s:%d: success\n", SFILE, __LINE__);
return 0;
}
gss_cred_id_t cred_handle = NULL;
krb5_gss_cred_id_t deleg_cred = NULL;
- _log("%s:%d: accept_sec_context input_token len %d\n",
- SFILE, __LINE__, input_token->length);
-
if (GSS_ERROR(kg_get_context(minor_status, &context)))
return(GSS_S_FAILURE);
GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
GSS_C_ACCEPT, &cred_handle,
NULL, NULL);
- _log("%s:%d: krb5_gss_acquire_cred returns %d, cred_handle %p\n",
- SFILE, __LINE__, major_status, cred_handle);
if (major_status != GSS_S_COMPLETE) {
code = *minor_status;
goto fail;
}
cred = (krb5_gss_cred_id_t) cred_handle;
- _log("%s:%d: cred=%p\n", SFILE, __LINE__, cred);
/* make sure the supplied credentials are valid for accept */
ptr = (unsigned char *) input_token->value;
- _log("%s:%d: here\n", SFILE, __LINE__);
if (!(code = g_verify_token_header((gss_OID) gss_mech_krb5,
&(ap_req.length),
&ptr, KG_TOK_CTX_AP_REQ,
major_status = GSS_S_CONTINUE_NEEDED;
code = KRB5KRB_AP_ERR_MSG_TYPE;
mech_used = gss_mech_krb5;
- _log("%s:%d: ooh, G_WRONG_TOKID! sending AP_ERR_MSG_TYPE\n",
- SFILE, __LINE__);
goto fail;
} else {
major_status = GSS_S_DEFECTIVE_TOKEN;
goto fail;
}
- _log("%s:%d: here\n", SFILE, __LINE__);
sptr = (char *) ptr;
TREAD_STR(sptr, ap_req.data, ap_req.length);
krb5_free_ap_req(context, request);
}
- _log("%s:%d: cred=%p mutual=%d major_status=%d (cont-need=%d)\n",
- SFILE, __LINE__, cred, gss_flags & GSS_C_MUTUAL_FLAG, major_status,
- GSS_S_CONTINUE_NEEDED);
if (cred
&& ((gss_flags & GSS_C_MUTUAL_FLAG)
|| (major_status == GSS_S_CONTINUE_NEEDED))) {
* The client is expecting a response, so we can send an
* error token back
*/
- _log("%s:%d: here\n", SFILE, __LINE__);
memset(&krb_error_data, 0, sizeof(krb_error_data));
code -= ERROR_TABLE_BASE_krb5;
else {
code = krb5_parse_name(context, "server/principal/name@unknown",
&krb_error_data.server);
- _log("%s:%d: here\n", SFILE, __LINE__);
if (code)
return major_status;
}
- _log("%s:%d: here\n", SFILE, __LINE__);
code = krb5_mk_error(context, &krb_error_data, &scratch);
if (cred == NULL) {
krb5_free_principal(context, krb_error_data.server);
}
if (code)
return (major_status);
- _log("%s:%d: here\n", SFILE, __LINE__);
tmsglen = scratch.length;
toktype = KG_TOK_CTX_ERROR;
- _log("%s:%d: here\n", SFILE, __LINE__);
token.length = g_token_size((gss_OID) mech_used, tmsglen);
- _log("%s:%d: here\n", SFILE, __LINE__);
token.value = (unsigned char *) xmalloc(token.length);
- _log("%s:%d: token.length=%d .value=%p\n", SFILE, __LINE__,
- token.length, token.value);
if (!token.value)
return (major_status);
- _log("%s:%d: here\n", SFILE, __LINE__);
ptr = token.value;
g_make_token_header((gss_OID) mech_used, tmsglen, &ptr, toktype);
TWRITE_STR(ptr, scratch.data, scratch.length);
krb5_free_data_contents(context, &scratch);
- _log("%s:%d: sending back error token size %d\n",
- SFILE, __LINE__, token.length);
*output_token = token;
}
if (!verifier_cred_handle && cred_handle) {
krb5_gss_release_cred(minor_status, cred_handle);
}
- _log("%s:%d: returning major status 0x%x\n", SFILE, __LINE__, major_status);
return (major_status);
}
return(GSS_S_CRED_UNAVAIL);
}
- _log("%s:%d: krb5_gss_keytab=%s ops=%p\n", SFILE, __LINE__,
- krb5_gss_keytab ? krb5_gss_keytab : "(null)", kt->ops);
-
if (desired_name != GSS_C_NO_NAME) {
princ = (krb5_principal) desired_name;
if ((code = krb5_kt_get_entry(context, kt, princ, 0, 0, &entry))) {
p = NULL;
if (err = krb5_kt_get_name(context, kt, ktname, sizeof(ktname)))
sprintf(ktname, "(error %d/%s)", err, error_message(err));
- _log("%s:%d: error %d/%s; desired_name=%s\n", SFILE, __LINE__,
- code, error_message(code),
- p ? p : "(error)");
free(p);
}
(void) krb5_kt_close(context, kt);
ctx_free = 0;
#ifdef CFX_EXERCISE
- {
- krb5_data *p1 = &ctx->there->data[0];
- _log("%s:%d: principal's first component is (%d) '%*s'\n",
- SFILE, __LINE__, p1->length, p1->length, p1->data);
- }
if (ctx->proto == 1
/* I think the RPC code may be broken. Don't mess around
if we're authenticating to "kadmin/whatever". */
goto resume_after_testing;
}
memcpy(token.value, hack_token, sizeof(hack_token));
- _log("%s:%d: sending bogus token to test unknown-TOK_ID handling\n",
- SFILE, __LINE__);
/* Can just fall through into the normal return path, because
it'll always return GSS_S_CONTINUE_NEEDED because we're
doing mutual authentication. */
}
if (0) {
resume_after_testing:
- _log("%s:%d: resuming after bogus-token test\n", SFILE, __LINE__);
token = ctx->init_token;
ctx->init_token.value = 0;
ctx->init_token.length = 0;
ptr = (unsigned char *) input_token->value;
- _log("%s:%d: here\n", SFILE, __LINE__);
if (g_verify_token_header((gss_OID) ctx->mech_used,
&(ap_rep.length),
&ptr, KG_TOK_CTX_AP_REP,
return(GSS_S_DEFECTIVE_TOKEN);
}
}
- _log("%s:%d: here\n", SFILE, __LINE__);
sptr = (char *) ptr; /* PC compiler bug */
TREAD_STR(sptr, ap_rep.data, ap_rep.length);
OM_uint32 major_status;
OM_uint32 tmp_min_stat;
- _log("%s:%d: %s input_token len %d\n", SFILE, __LINE__, __func__,
- input_token == GSS_C_NO_BUFFER ? -1 : input_token->length);
-
if (GSS_ERROR(kg_get_context(minor_status, &context)))
return(GSS_S_FAILURE);
#define FLAG_WRAP_CONFIDENTIAL 0x02
#define FLAG_ACCEPTOR_SUBKEY 0x04
-void
-_log_block(const char *file, int line, const char *label,
- void *vptr, size_t len)
-{
- char b[8 * 4 + 4];
- int i, j;
- if (strrchr(file, '/'))
- file = 1 + strrchr(file, '/');
-#if 0
- _log("%s:%d: %s: %d at %p\n", file, line, label, len, vptr);
- for (i = 0; i < (len + 7) / 8; i++) {
- unsigned char *base = (i * 8) + (unsigned char *)vptr;
- b[0] = 0;
- for (j = 0; j < 8 && j < (len - i * 8); j++)
- sprintf(b+strlen(b), " %02x", base[j]);
- _log("\t\t%04x/@%p:%s\n", 8 * i, base, b);
- }
-#else
- _log("%s:%d: %s: %d at %p [omitted]\n", file, line, label, len, vptr);
-#endif
-}
-
-#define SFILE (strrchr(__FILE__,'/') ? 1+strrchr(__FILE__,'/') : __FILE__)
-
krb5_error_code
gss_krb5int_make_seal_token_v3 (krb5_context context,
krb5_gss_ctx_id_rec *ctx,
? KG_USAGE_INITIATOR_SIGN
: KG_USAGE_ACCEPTOR_SIGN));
if (ctx->have_acceptor_subkey) {
- _log("%s:%d: using acceptor subkey\n", SFILE, __LINE__);
key = ctx->acceptor_subkey;
} else {
- _log("%s:%d: using main key\n", SFILE, __LINE__);
key = ctx->enc;
}
- _log("%s:%d: wrap input token: %d @%p toktype=0x%x\n", SFILE, __LINE__,
- message->length, message->value, toktype);
-
#ifdef CFX_EXERCISE
{
static int initialized = 0;
#else
ec = 0;
#endif
- _log("%s:%d: ec=%d\n", SFILE, __LINE__, ec);
plain.length = message->length + 16 + ec;
plain.data = malloc(message->length + 16 + ec);
if (plain.data == NULL)
plain.data = 0;
if (err)
goto error;
- _log("%s:%d: just encrypted:\n"
- "\t(key=%d/%02x%02x..., usage=%d, plain.length=%d,\n"
- "\t ciphertext=%d/%02x%02x...)\n",
- SFILE, __LINE__, key->enctype,
- key->contents[0], key->contents[1],
- key_usage, plain.length,
- cipher.ciphertext.length,
- 0xff & cipher.ciphertext.data[0],
- 0xff & cipher.ciphertext.data[1]);
/* Now that we know we're returning a valid token.... */
ctx->seq_send++;
if (plain.data == NULL)
return ENOMEM;
- _log("%s:%d: cksumtype=%d\n", SFILE, __LINE__, ctx->cksumtype);
if (ctx->cksum_size > 0xffff)
abort();
sum.contents = outbuf + 16 + message2->length;
sum.length = ctx->cksum_size;
- _log("%s:%d: checksum @%p outbuf @%p offset %d\n", SFILE, __LINE__,
- sum.contents, outbuf, sum.contents - outbuf);
- _log_block(SFILE, __LINE__, "checksum input",
- plain.data, plain.length);
err = krb5_c_make_checksum(context, ctx->cksumtype, key,
key_usage, &plain, &sum);
free(outbuf);
goto error;
}
- _log_block(SFILE, __LINE__, "checksum result",
- sum.contents, sum.length);
if (sum.length != ctx->cksum_size)
abort();
memcpy(outbuf + 16 + message2->length, sum.contents, ctx->cksum_size);
token->value = outbuf;
token->length = bufsize;
- _log_block(SFILE, __LINE__, "output token", token->value, token->length);
return 0;
error:
? KG_USAGE_INITIATOR_SIGN
: KG_USAGE_ACCEPTOR_SIGN));
-#define LOG() _log("%s:%d: here\n", SFILE, __LINE__)
-#define DEFECTIVE do{LOG();goto defective;}while(0)
-
- _log ("%s:%d: bodysize %d ptr @%p: %02x %02x\n", SFILE, __LINE__,
- bodysize, ptr, ptr[0], ptr[1]);
-
/* Oops. I wrote this code assuming ptr would be at the start of
the token header. */
ptr -= 2;
bodysize += 2;
- _log_block(SFILE, __LINE__, "input token", ptr, bodysize);
-
if (bodysize < 16) {
- LOG();
defective:
*minor_status = 0;
return GSS_S_DEFECTIVE_TOKEN;
}
- LOG();
if ((ptr[2] & FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) {
*minor_status = G_BAD_DIRECTION;
return GSS_S_BAD_SIG;
}
- LOG();
/* Two things to note here.
key, the one not asserted by the acceptor, will have the same
value in that case, though, so we can just ignore the flag. */
if (ctx->have_acceptor_subkey && (ptr[2] & FLAG_ACCEPTOR_SUBKEY)) {
- _log("%s:%d: sender used acceptor subkey\n", SFILE, __LINE__);
key = ctx->acceptor_subkey;
} else {
- _log("%s:%d: sender used its own key\n", SFILE, __LINE__);
key = ctx->enc;
}
if (toktype == KG_TOK_WRAP_MSG) {
if (load_16_be(ptr) != 0x0504)
- DEFECTIVE;
+ goto defective;
if (ptr[3] != 0xff)
- DEFECTIVE;
+ goto defective;
ec = load_16_be(ptr+4);
rrc = load_16_be(ptr+6);
seqnum = load_64_be(ptr+8);
krb5_enc_data cipher;
unsigned char *althdr;
- LOG();
if (conf_state)
*conf_state = 1;
/* Do we have no decrypt_size function?
plain.data = malloc(plain.length);
if (plain.data == NULL)
goto no_mem;
- _log("%s:%d: about to decrypt:\n"
- "\t(key=%d/%02x%02x..., usage=%d, ciphertext=%d/%02x%02x...)\n",
- SFILE, __LINE__, key->enctype,
- key->contents[0], key->contents[1],
- key_usage,
- cipher.ciphertext.length,
- 0xff & cipher.ciphertext.data[0],
- 0xff & cipher.ciphertext.data[1]);
err = krb5_c_decrypt(context, key, key_usage, 0,
&cipher, &plain);
if (err) {
free(plain.data);
- _log("%s:%d: error %ld/%s\n", SFILE, __LINE__,
- (long) err, error_message(err));
goto error;
}
/* Don't use bodysize here! Use the fact that
cipher.ciphertext.length has been adjusted to the
correct length. */
- LOG();
althdr = plain.data + plain.length - 16;
if (load_16_be(althdr) != 0x0504
|| althdr[2] != ptr[2]
|| althdr[3] != ptr[3]
|| memcmp(althdr+8, ptr+8, 8))
- DEFECTIVE;
+ goto defective;
message_buffer->value = plain.data;
- _log("%s:%d: plaintext len=%d, ec=%d\n", SFILE, __LINE__,
- plain.length, ec);
message_buffer->length = plain.length - ec - 16;
- _log("%s:%d: decrypted token %d @%p\n", SFILE, __LINE__,
- message_buffer->length, message_buffer->value);
} else {
/* no confidentiality */
- LOG();
if (conf_state)
*conf_state = 0;
if (ec + 16 < ec)
/* overflow check */
- DEFECTIVE;
- LOG();
+ goto defective;
if (ec + 16 > bodysize)
- DEFECTIVE;
- LOG();
+ goto defective;
/* We have: header | msg | cksum.
We need cksum(msg | header).
Rotate the first two. */
sum.length = ec;
if (sum.length != ctx->cksum_size) {
*minor_status = 0;
- LOG();
return GSS_S_BAD_SIG;
}
sum.contents = ptr+bodysize-ec;
sum.checksum_type = ctx->cksumtype;
- _log_block(SFILE, __LINE__, "checksum data input",
- plain.data, plain.length);
- _log_block(SFILE, __LINE__, "checksum to test",
- sum.contents, sum.length);
err = krb5_c_verify_checksum(context, key, key_usage,
&plain, &sum, &valid);
if (err)
goto error;
- _log("%s:%d: valid=%d\n", SFILE, __LINE__, valid);
if (!valid) {
- LOG();
*minor_status = 0;
return GSS_S_BAD_SIG;
}
goto no_mem;
memcpy(message_buffer->value, plain.data, message_buffer->length);
}
- LOG();
err = g_order_check(&ctx->seqstate, seqnum);
*minor_status = 0;
- _log("%s:%d: g_order_check => %d/%s, unseal %s\n", SFILE, __LINE__,
- err, err ? error_message(err) : "No error",
- err ? "failed" : "passed");
return err;
} else if (toktype == KG_TOK_MIC_MSG) {
/* wrap token, no confidentiality */
- LOG();
if (load_16_be(ptr) != 0x0404)
- DEFECTIVE;
- LOG();
+ goto defective;
verify_mic_1:
- LOG();
if (ptr[3] != 0xff)
- DEFECTIVE;
- _log("%s:%d: at ptr+4 %p: %02x %02x %02x %02x\n", SFILE, __LINE__,
- ptr+4, ptr[4], ptr[5], ptr[6], ptr[7]);
+ goto defective;
if (load_32_be(ptr+4) != 0xffffffffL)
- DEFECTIVE;
- LOG();
+ goto defective;
seqnum = load_64_be(ptr+8);
plain.length = message_buffer->length + 16;
plain.data = malloc(plain.length);
sum.length = bodysize - 16;
sum.contents = ptr + 16;
sum.checksum_type = ctx->cksumtype;
- _log("%s:%d: sum.length = %d\n", SFILE, __LINE__, sum.length);
- _log_block(SFILE, __LINE__, "checksum data input",
- plain.data, plain.length);
- _log_block(SFILE, __LINE__, "checksum to test",
- sum.contents, sum.length);
err = krb5_c_verify_checksum(context, key, key_usage,
&plain, &sum, &valid);
if (err) {
error:
free(plain.data);
- LOG();
*minor_status = err;
return GSS_S_BAD_SIG; /* XXX */
}
- LOG();
if (!valid) {
free(plain.data);
*minor_status = 0;
- LOG();
return GSS_S_BAD_SIG;
}
- LOG();
err = g_order_check(&ctx->seqstate, seqnum);
*minor_status = 0;
return err;
} else if (toktype == KG_TOK_DEL_CTX) {
- LOG();
if (load_16_be(ptr) != 0x0405)
- DEFECTIVE;
- LOG();
+ goto defective;
message_buffer = &empty_message;
goto verify_mic_1;
} else {
- LOG();
- DEFECTIVE;
+ goto defective;
}
}
int err;
int toktype2;
- _log_block2("token to unseal",
- input_token_buffer->value, input_token_buffer->length);
-
/* validate the context handle */
if (! kg_validate_ctx_id(context_handle)) {
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
!ctx->proto);
if (err) {
*minor_status = err;
- _log("%s:%d: g_verify_token_header returns %d/%s\n", SFILE, __LINE__,
- err, error_message(err));
return GSS_S_DEFECTIVE_TOKEN;
}
int *conf_state;
int *qop_state;
{
- _log("%s:%d: input length %d\n", SFILE, __LINE__,
- input_message_buffer->length);
if (input_message_buffer->length == 0) {
if (fork() == 0)
abort();
/* "unseal" the token */
- _log("%s:%d: here\n", SFILE, __LINE__);
if (GSS_ERROR(majerr = kg_unseal(context, minor_status, ctx, token_buffer,
GSS_C_NO_BUFFER, NULL, NULL,
KG_TOK_DEL_CTX)))
return(majerr);
- _log("%s:%d: here\n", SFILE, __LINE__);
/* that's it. delete the context */
if (GSS_ERROR(kg_get_context(minor_status, &context)))
return(GSS_S_FAILURE);
- _log_block2("krb5_gss_unseal token", input_message_buffer->value,
- input_message_buffer->length);
return(kg_unseal(context, minor_status, context_handle,
input_message_buffer, output_message_buffer,
conf_state, qop_state, KG_TOK_SEAL_MSG));
if (GSS_ERROR(kg_get_context(minor_status, &context)))
return(GSS_S_FAILURE);
- _log("%s:%d: here\n", SFILE, __LINE__);
rstat = kg_unseal(context, minor_status, context_handle,
input_message_buffer, output_message_buffer,
conf_state, &qstate, KG_TOK_WRAP_MSG);
- _log("%s:%d: here\n", SFILE, __LINE__);
if (!rstat && qop_state)
*qop_state = (gss_qop_t) qstate;
return(rstat);
return(GSS_S_FAILURE);
- _log("%s:%d: here\n", SFILE, __LINE__);
return(kg_unseal(context, minor_status, context_handle,
token_buffer, message_buffer,
NULL, qop_state, KG_TOK_SIGN_MSG));
return(GSS_S_FAILURE);
- _log("%s:%d: here\n", SFILE, __LINE__);
rstat = kg_unseal(context, minor_status, context_handle,
token_buffer, message_buffer,
NULL, &qstate, KG_TOK_MIC_MSG);
- _log("%s:%d: here\n", SFILE, __LINE__);
if (!rstat && qop_state)
*qop_state = (gss_qop_t) qstate;
return(rstat);