Пример #1
0
int
main(int argc, char **argv)
{
    OM_uint32 minor_status, maj_stat;
    gss_buffer_desc data;
    int ret;

    maj_stat = gss_oid_to_str(&minor_status, GSS_KRB5_MECHANISM, &data);
    if (GSS_ERROR(maj_stat))
	errx(1, "gss_oid_to_str failed");

    ret = strncmp(data.value, "1 2 840 113554 1 2 2", data.length);
    gss_release_buffer(&maj_stat, &data);
    if (ret)
	return 1;

    maj_stat = gss_oid_to_str(&minor_status, GSS_C_NT_EXPORT_NAME, &data);
    if (GSS_ERROR(maj_stat))
	errx(1, "gss_oid_to_str failed");

    ret = strncmp(data.value, "1 3 6 1 5 6 4", data.length);
    gss_release_buffer(&maj_stat, &data);
    if (ret)
	return 1;

    return 0;
}
Пример #2
0
static void gt_gss_error(char *name, gss_OID mech, uint32_t maj, uint32_t min)
{
    AUTOCLEAN(struct gss_err err, autofreegsserr) = { {0}, 0, 0};
    OM_uint32 msgctx;

    fprintf(stderr, "[%s] Failed with:", name);

    if (mech != GSS_C_NO_OID) {
        err.maj = gss_oid_to_str(&err.min, mech, &err.buf);
        if (err.maj != GSS_S_COMPLETE) return;
        fprintf(stderr, " (OID: %s)", (char *)err.buf.value);
        (void)gss_release_buffer(&err.min, &err.buf);
    }

    msgctx = 0;
    err.maj = gss_display_status(&err.min, maj, GSS_C_GSS_CODE,
                                 mech, &msgctx, &err.buf);
    if (err.maj != GSS_S_COMPLETE) return;
    fprintf(stderr, " %s,", (char *)err.buf.value);
    (void)gss_release_buffer(&err.min, &err.buf);

    msgctx = 0;
    err.maj = gss_display_status(&err.min, min, GSS_C_MECH_CODE,
                                 mech, &msgctx, &err.buf);
    if (err.maj != GSS_S_COMPLETE) return;
    fprintf(stderr, " %s\n", (char *)err.buf.value);
    (void)gss_release_buffer(&err.min, &err.buf);
}
Пример #3
0
void gp_fmt_status(gss_OID mech, uint32_t maj, uint32_t min,
                   char *buf, size_t buf_size)
{
    uint32_t msgctx;
    uint32_t discard;
    gss_buffer_desc tmp;
    size_t used = 0;

    if (mech != GSS_C_NO_OID) {
        gss_oid_to_str(&discard, mech, &tmp);
        used += gp_append(buf + used, buf_size - used,
                          "(OID: %s) ", (char *)tmp.value);
        gss_release_buffer(&discard, &tmp);
    }

    msgctx = 0;
    gss_display_status(&discard, maj, GSS_C_GSS_CODE, mech, &msgctx, &tmp);
    used += gp_append(buf + used, buf_size - used, "%s, ", (char *)tmp.value);
    gss_release_buffer(&discard, &tmp);

    msgctx = 0;
    gss_display_status(&discard, min, GSS_C_MECH_CODE, mech, &msgctx, &tmp);
    used += gp_append(buf + used, buf_size - used, "%s", (char *)tmp.value);
    gss_release_buffer(&discard, &tmp);
}
Пример #4
0
int
supported_mechanisms(void *argptr, int argc, char **argv)
{
    OM_uint32 maj_stat, min_stat;
    gss_OID_set mechs;
    rtbl_t ct;
    size_t i;

    maj_stat = gss_indicate_mechs(&min_stat, &mechs);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_indicate_mechs failed");

    printf("Supported mechanisms:\n");

    ct = rtbl_create();
    if (ct == NULL)
	errx(1, "rtbl_create");

    rtbl_set_separator(ct, "  ");
    rtbl_add_column(ct, COL_OID, 0);
    rtbl_add_column(ct, COL_NAME, 0);
    rtbl_add_column(ct, COL_DESC, 0);
    rtbl_add_column(ct, COL_SASL, 0);

    for (i = 0; i < mechs->count; i++) {
	gss_buffer_desc str, sasl_name, mech_name, mech_desc;

	maj_stat = gss_oid_to_str(&min_stat, &mechs->elements[i], &str);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gss_oid_to_str failed");

	rtbl_add_column_entryv(ct, COL_OID, "%.*s",
			       (int)str.length, (char *)str.value);
	gss_release_buffer(&min_stat, &str);

	(void)gss_inquire_saslname_for_mech(&min_stat,
					    &mechs->elements[i],
					    &sasl_name,
					    &mech_name,
					    &mech_desc);

	rtbl_add_column_entryv(ct, COL_NAME, "%.*s",
			       (int)mech_name.length, (char *)mech_name.value);
	rtbl_add_column_entryv(ct, COL_DESC, "%.*s",
			       (int)mech_desc.length, (char *)mech_desc.value);
	rtbl_add_column_entryv(ct, COL_SASL, "%.*s",
			       (int)sasl_name.length, (char *)sasl_name.value);

	gss_release_buffer(&min_stat, &mech_name);
	gss_release_buffer(&min_stat, &mech_desc);
	gss_release_buffer(&min_stat, &sasl_name);

    }
    gss_release_oid_set(&min_stat, &mechs);

    rtbl_format(ct, stdout);
    rtbl_destroy(ct);

    return 0;
}
Пример #5
0
Файл: common.c Проект: PADL/krb5
void
display_oid(const char *tag, gss_OID oid)
{
    OM_uint32 major, minor;
    gss_buffer_desc buf;

    major = gss_oid_to_str(&minor, oid, &buf);
    check_gsserr("gss_oid_to_str", major, minor);
    if (tag != NULL)
        printf("%s:\t", tag);
    printf("%.*s\n", (int)buf.length, (char *)buf.value);
    (void)gss_release_buffer(&minor, &buf);
}
Пример #6
0
int
supported_mechanisms(void *argptr, int argc, char **argv)
{
    OM_uint32 maj_stat, min_stat;
    gss_OID_set mechs;
    rtbl_t ct;
    size_t i;

    maj_stat = gss_indicate_mechs(&min_stat, &mechs);
    if (maj_stat != GSS_S_COMPLETE)
	errx(1, "gss_indicate_mechs failed");

    printf("Supported mechanisms:\n");

    ct = rtbl_create();
    if (ct == NULL)
	errx(1, "rtbl_create");

    rtbl_set_separator(ct, "  ");
    rtbl_add_column(ct, COL_OID, 0);
    rtbl_add_column(ct, COL_NAME, 0);

    for (i = 0; i < mechs->count; i++) {
	gss_buffer_desc name;

	maj_stat = gss_oid_to_str(&min_stat, &mechs->elements[i], &name);
	if (maj_stat != GSS_S_COMPLETE)
	    errx(1, "gss_oid_to_str failed");

	rtbl_add_column_entryv(ct, COL_OID, "%.*s",
			       (int)name.length, (char *)name.value);
	gss_release_buffer(&min_stat, &name);

	if (gss_oid_equal(&mechs->elements[i], GSS_KRB5_MECHANISM))
	    rtbl_add_column_entry(ct, COL_NAME, "Kerberos 5");
	else if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM))
	    rtbl_add_column_entry(ct, COL_NAME, "SPNEGO");
	else if (gss_oid_equal(&mechs->elements[i], GSS_NTLM_MECHANISM))
	    rtbl_add_column_entry(ct, COL_NAME, "NTLM");
    }
    gss_release_oid_set(&min_stat, &mechs);

    rtbl_format(ct, stdout);
    rtbl_destroy(ct);

    return 0;
}
Пример #7
0
static OM_uint32
displayOID(OM_uint32 *minor, gss_OID oid, char *tag)
{
    OM_uint32 major, tmp_minor;
    gss_buffer_desc buf;

    major = gss_oid_to_str(minor, oid, &buf);
    if (GSS_ERROR(major)) {
        displayStatus("gss_oid_to_str", major, *minor);
        return major;
    }

    printf("%s:\t%s\n", tag, (char *)buf.value);

    gss_release_buffer(&tmp_minor, &buf);

    return GSS_S_COMPLETE;
}
Пример #8
0
int main(int argc,char *argv[])
{
     char strbuf[BUFSIZE];
     OM_uint32 oidvec[MAXOID];
     OM_uint32 oidvecsize;
     unsigned char enc_oid_buf[BUFSIZE];
     gss_OID oid = NULL;
     gss_buffer_desc buf;
     OM_uint32 stat, minor;

     while (fgets(strbuf,BUFSIZE,stdin)!=NULL) {
	  if ((strbuf[0]!='#') && (strlen(strbuf) > 1)) {
	       buf.length = strlen(strbuf) - 1;
	       buf.value = (void *) strbuf;
	       stat = gss_str_to_oid (&minor, &buf, &oid);
	       printf ("gss_str_to_oid returns %u, %u\n", stat, minor);
	       print_oid (oid);
	       stat = gss_oid_to_str (&minor, oid, &buf);
	       printf ("gss_oid_to_str returns %u, %u\n", stat, minor);
	       printf ("string form of OID is \"%*.*s\"\n", buf.length, buf.length, buf.value);
	       ilugss_free (oid);
	  }
     }
}
Пример #9
0
int
main(int argc, char **argv)
{
    const char *name = "*****@*****.**";
    OM_uint32 major, minor;
    gss_name_t gss_name;
    gss_buffer_desc buf;
    gss_OID name_oid;

    gss_name = import_name(name);

    major = gss_display_name(&minor, gss_name, &buf, &name_oid);
    check_gsserr("gss_display_name", major, minor);
    printf("name is: %.*s\n", (int)buf.length, (char *)buf.value);
    (void)gss_release_buffer(&minor, &buf);

    major = gss_oid_to_str(&minor, name_oid, &buf);
    check_gsserr("gss_oid_to_str", major, minor);
    printf("name type is: %.*s\n", (int)buf.length, (char *)buf.value);
    (void)gss_release_buffer(&minor, &buf);
    (void)gss_release_name(&minor, &gss_name);

    return 0;
}
Пример #10
0
static bool_t
Svcauth_gss_accept_sec_context(struct svc_req *rqst, struct rpc_gss_init_res *gr)
{
  struct svc_rpc_gss_data *gd;
  struct rpc_gss_cred *gc;
  gss_buffer_desc recv_tok, seqbuf;
  gss_OID mech;
  OM_uint32 maj_stat = 0, min_stat = 0, ret_flags, seq;

  gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth);
  gc = (struct rpc_gss_cred *)rqst->rq_clntcred;
  memset(gr, 0, sizeof(*gr));

  /* Deserialize arguments. */
  memset(&recv_tok, 0, sizeof(recv_tok));

  if(!svc_getargs(rqst->rq_xprt, (xdrproc_t)xdr_rpc_gss_init_args, (caddr_t) & recv_tok))
    return (FALSE);

  gr->gr_major = gss_accept_sec_context(&gr->gr_minor,
                                        &gd->ctx,
                                        svcauth_gss_creds,
                                        &recv_tok,
                                        GSS_C_NO_CHANNEL_BINDINGS,
                                        &gd->client_name,
                                        &mech, &gr->gr_token, &ret_flags, NULL, NULL);

  svc_freeargs(rqst->rq_xprt, (xdrproc_t)xdr_rpc_gss_init_args, (caddr_t) & recv_tok);

  if(gr->gr_major != GSS_S_COMPLETE && gr->gr_major != GSS_S_CONTINUE_NEEDED)
    {
      sockaddr_t addr;
      char ipstring[SOCK_NAME_MAX];
      copy_xprt_addr(&addr, rqst->rq_xprt);
      sprint_sockaddr(&addr, ipstring, sizeof(ipstring));

      LogWarn(COMPONENT_RPCSEC_GSS,
              "Bad authentication major=%u minor=%u addr=%s",
              gr->gr_major, gr->gr_minor, ipstring);
      gd->ctx = GSS_C_NO_CONTEXT;
      goto errout;
    }
  /*
   * ANDROS: krb5 mechglue returns ctx of size 8 - two pointers,
   * one to the mechanism oid, one to the internal_ctx_id
   */
  if((gr->gr_ctx.value = Mem_Alloc(sizeof(gss_union_ctx_id_desc))) == NULL)
    {
      LogCrit(COMPONENT_RPCSEC_GSS,
              "svcauth_gss_accept_context: out of memory");
      goto errout;
    }
  memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc));
  gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc);

  /* gr->gr_win = 0x00000005; ANDROS: for debugging linux kernel version...  */
  gr->gr_win = sizeof(gd->seqmask) * 8;

  /* Save client info. */
  gd->sec.mech = mech;
  gd->sec.qop = GSS_C_QOP_DEFAULT;
  gd->sec.svc = gc->gc_svc;
  gd->seq = gc->gc_seq;
  gd->win = gr->gr_win;

  if(gr->gr_major == GSS_S_COMPLETE)
    {
#ifdef SPKM
      /* spkm3: no src_name (anonymous) */
      if(!g_OID_equal(gss_mech_spkm3, mech))
        {
#endif
          maj_stat = gss_display_name(&min_stat, gd->client_name,
                                      &gd->cname, &gd->sec.mech);
	  LogFullDebug(COMPONENT_RPCSEC_GSS,
	               "cname.val: %s  cname.len: %d",
	               (char *)gd->cname.value, (int)gd->cname.length);
#ifdef SPKM
        }
#endif
      if(maj_stat != GSS_S_COMPLETE)
        {
        }
#ifdef HAVE_HEIMDAL
#else
      if(isFullDebug(COMPONENT_RPCSEC_GSS))
        {
          gss_buffer_desc mechname;

          gss_oid_to_str(&min_stat, mech, &mechname);

          gss_release_buffer(&min_stat, &mechname);
        }
#endif
      seq = htonl(gr->gr_win);
      seqbuf.value = &seq;
      seqbuf.length = sizeof(seq);

      gss_release_buffer(&min_stat, &gd->checksum);
      LogFullDebug(COMPONENT_RPCSEC_GSS,
                   "gss_sign in sec_accept_context");
      maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT, &seqbuf, &gd->checksum);

      if(maj_stat != GSS_S_COMPLETE)
        {
          goto errout;
        }

      rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS;
      rqst->rq_xprt->xp_verf.oa_base = gd->checksum.value;
      rqst->rq_xprt->xp_verf.oa_length = gd->checksum.length;
    }
  return (TRUE);
 errout:
  gss_release_buffer(&min_stat, &gr->gr_token);
  return (FALSE);
}
Пример #11
0
static bool
svcauth_gss_accept_sec_context(struct svc_req *req,
			       struct svc_rpc_gss_data *gd,
			       struct rpc_gss_init_res *gr)
{
	struct rpc_gss_cred *gc;
	gss_buffer_desc recv_tok, seqbuf, checksum;
	gss_OID mech;
	OM_uint32 maj_stat = 0, min_stat = 0, ret_flags, seq;
#define INDEF_EXPIRE 60*60*24	/* from mit k5 src/lib/rpc/svc_auth_gssapi.c */
	OM_uint32 time_rec;

	gc = (struct rpc_gss_cred *)req->rq_clntcred;
	memset(gr, 0, sizeof(*gr));

	/* Deserialize arguments. */
	memset(&recv_tok, 0, sizeof(recv_tok));

	if (!svc_getargs
	    (req->rq_xprt, req, (xdrproc_t) xdr_rpc_gss_init_args,
	     (caddr_t) &recv_tok, NULL /* u_data */))
		return (false);

	gr->gr_major =
	    gss_accept_sec_context(&gr->gr_minor, &gd->ctx, svcauth_gss_creds,
				   &recv_tok, GSS_C_NO_CHANNEL_BINDINGS,
				   &gd->client_name, &mech, &gr->gr_token,
				   &ret_flags, &time_rec, NULL);

	svc_freeargs(req->rq_xprt, req, (xdrproc_t) xdr_rpc_gss_init_args,
		     (caddr_t) &recv_tok);

	if ((gr->gr_major != GSS_S_COMPLETE)
	    && (gr->gr_major != GSS_S_CONTINUE_NEEDED)) {
		__warnx(TIRPC_DEBUG_FLAG_AUTH,
			"%s: auth failed major=%u minor=%u", __func__,
			gr->gr_major, gr->gr_minor);
		gd->ctx = GSS_C_NO_CONTEXT;
		gss_release_buffer(&min_stat, &gr->gr_token);
		return (false);
	}
	/* ANDROS: krb5 mechglue returns ctx of size 8 - two pointers,
	 * one to the mechanism oid, one to the internal_ctx_id */
	gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc));
	memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc));
	gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc);

	/* ANDROS: change for debugging linux kernel version...
	   gr->gr_win = 0x00000005;
	 */
	gr->gr_win = sizeof(gd->seqmask) * 8;

	/* Save client info. */
	gd->sec.mech = mech;
	gd->sec.qop = GSS_C_QOP_DEFAULT;
	gd->sec.svc = gc->gc_svc;
	gd->win = gr->gr_win;

	if (time_rec == GSS_C_INDEFINITE) time_rec = INDEF_EXPIRE;
	if (time_rec > 10) time_rec -= 5;
	gd->endtime = time_rec + get_time_fast();

	if (gr->gr_major == GSS_S_COMPLETE) {
		maj_stat =
		    gss_display_name(&min_stat, gd->client_name, &gd->cname,
				     &gd->sec.mech);
		if (maj_stat != GSS_S_COMPLETE) {
			__warnx(TIRPC_DEBUG_FLAG_AUTH,
				"%s: display_name major=%u minor=%u", __func__,
				maj_stat, min_stat);
			gss_release_buffer(&min_stat, &gr->gr_token);
			return (false);
		}
#ifdef DEBUG
#ifdef HAVE_KRB5
		{
			gss_buffer_desc mechname;
			gss_oid_to_str(&min_stat, mech, &mechname);
			__warnx(TIRPC_DEBUG_FLAG_AUTH,
				"%s: accepted context for %.*s with "
				"<mech %.*s, qop %d, svc %d>", __func__,
				gd->cname.length, (char *)gd->cname.value,
				mechname.length, (char *)mechname.value,
				gd->sec.qop, gd->sec.svc);
			gss_release_buffer(&min_stat, &mechname);
		}
#elif HAVE_HEIMDAL
		__warnx(TIRPC_DEBUG_FLAG_AUTH,
			"%s: accepted context for %.*s with "
			"<mech {}, qop %d, svc %d>", __func__, gd->cname.length,
			(char *)gd->cname.value, gd->sec.qop, gd->sec.svc);
#endif
#endif				/* DEBUG */
		seq = htonl(gr->gr_win);
		seqbuf.value = &seq;
		seqbuf.length = sizeof(seq);

		gss_release_buffer(&min_stat, &gd->checksum);

		maj_stat =
		    gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT, &seqbuf,
			     &checksum);

		if (maj_stat != GSS_S_COMPLETE) {
			gss_release_buffer(&min_stat, &gr->gr_token);
			return (false);
		}

		/* XXX ref? (assert gd->locked?) */
		req->rq_verf.oa_flavor = RPCSEC_GSS;
		req->rq_verf.oa_base = checksum.value;
		req->rq_verf.oa_length = checksum.length;
	}
	return (true);
}
Пример #12
0
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_display_status(OM_uint32 *minor_status,
    OM_uint32 status_value,
    int status_type,
    const gss_OID mech_type,
    OM_uint32 *message_content,
    gss_buffer_t status_string)
{
	OM_uint32 major_status;

	_mg_buffer_zero(status_string);
	*message_content = 0;

	major_status = _gss_mg_get_error(mech_type, status_type,
					 status_value, status_string);
	if (major_status == GSS_S_COMPLETE) {

	    *message_content = 0;
	    *minor_status = 0;
	    return GSS_S_COMPLETE;
	}

	*minor_status = 0;
	switch (status_type) {
	case GSS_C_GSS_CODE: {
	    	char *buf = NULL;
		int e;

		if (GSS_SUPPLEMENTARY_INFO(status_value))
		    e = asprintf(&buf, "%s", supplementary_error(
		        GSS_SUPPLEMENTARY_INFO(status_value)));
		else
		    e = asprintf (&buf, "%s %s",
		        calling_error(GSS_CALLING_ERROR(status_value)),
			routine_error(GSS_ROUTINE_ERROR(status_value)));

		if (e < 0 || buf == NULL)
		    break;

		status_string->length = strlen(buf);
		status_string->value  = buf;

		return GSS_S_COMPLETE;
	}
	case GSS_C_MECH_CODE: {
		OM_uint32 maj_junk, min_junk;
		gss_buffer_desc oid;
		char *buf = NULL;
		int e;

		maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid);
		if (maj_junk != GSS_S_COMPLETE) {
		    oid.value = rk_UNCONST("unknown");
		    oid.length = 7;
		}
		
		e = asprintf (&buf, "unknown mech-code %lu for mech %.*s",
			  (unsigned long)status_value,
			  (int)oid.length, (char *)oid.value);
		if (maj_junk == GSS_S_COMPLETE)
		    gss_release_buffer(&min_junk, &oid);

		if (e < 0 || buf == NULL)
		    break;

		status_string->length = strlen(buf);
		status_string->value  = buf;

		return GSS_S_COMPLETE;
	}
	}
	_mg_buffer_zero(status_string);
	return (GSS_S_BAD_STATUS);
}
Пример #13
0
static bool_t
svcauth_gss_accept_sec_context(struct svc_req *rqst,
			       struct rpc_gss_init_res *gr)
{
	struct svc_rpc_gss_data	*gd;
	struct rpc_gss_cred	*gc;
	gss_buffer_desc		 recv_tok, seqbuf, checksum;
	gss_OID			 mech;
	OM_uint32		 maj_stat = 0, min_stat = 0, ret_flags, seq;

	log_debug("in svcauth_gss_accept_context()");

	gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth);
	gc = (struct rpc_gss_cred *)rqst->rq_clntcred;
	memset(gr, 0, sizeof(*gr));

	/* Deserialize arguments. */
	memset(&recv_tok, 0, sizeof(recv_tok));

	if (!svc_getargs(rqst->rq_xprt, (xdrproc_t)xdr_rpc_gss_init_args,
			 (caddr_t)&recv_tok))
		return (FALSE);

	gr->gr_major = gss_accept_sec_context(&gr->gr_minor,
					      &gd->ctx,
					      _svcauth_gss_creds,
					      &recv_tok,
					      GSS_C_NO_CHANNEL_BINDINGS,
					      &gd->client_name,
					      &mech,
					      &gr->gr_token,
					      &ret_flags,
					      NULL,
					      NULL);

	if (gr->gr_major != GSS_S_COMPLETE &&
	    gr->gr_major != GSS_S_CONTINUE_NEEDED) {
		log_status("accept_sec_context", gr->gr_major, gr->gr_minor);
		gd->ctx = GSS_C_NO_CONTEXT;
		gss_release_buffer(&min_stat, &gr->gr_token);
		return (FALSE);
	}
	/* ANDROS: krb5 mechglue returns ctx of size 8 - two pointers,
	 * one to the mechanism oid, one to the internal_ctx_id */
	if ((gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc))) == NULL) {
		fprintf(stderr, "svcauth_gss_accept_context: out of memory\n");
		return (FALSE);
	}
	memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc));
	gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc);

	/* ANDROS: change for debugging linux kernel version...
	gr->gr_win = sizeof(gd->seqmask) * 8;
	*/
	gr->gr_win = 0x00000005;

	/* Save client info. */
	gd->sec.mech = mech;
	gd->sec.qop = GSS_C_QOP_DEFAULT;
	gd->sec.svc = gc->gc_svc;
	gd->seq = gc->gc_seq;
	gd->win = gr->gr_win;

	if (gr->gr_major == GSS_S_COMPLETE) {
		maj_stat = gss_display_name(&min_stat, gd->client_name,
					    &gd->cname, &gd->sec.mech);
		if (maj_stat != GSS_S_COMPLETE) {
			log_status("display_name", maj_stat, min_stat);
			return (FALSE);
		}
#ifdef DEBUG
#ifdef HAVE_KRB5
		{
			gss_buffer_desc mechname;

			gss_oid_to_str(&min_stat, mech, &mechname);

			log_debug("accepted context for %.*s with "
				  "<mech %.*s, qop %d, svc %d>",
				  gd->cname.length, (char *)gd->cname.value,
				  mechname.length, (char *)mechname.value,
				  gd->sec.qop, gd->sec.svc);

			gss_release_buffer(&min_stat, &mechname);
		}
#elif HAVE_HEIMDAL
		log_debug("accepted context for %.*s with "
			  "<mech {}, qop %d, svc %d>",
			  gd->cname.length, (char *)gd->cname.value,
			  gd->sec.qop, gd->sec.svc);
#endif
#endif /* DEBUG */
		seq = htonl(gr->gr_win);
		seqbuf.value = &seq;
		seqbuf.length = sizeof(seq);

		maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT,
				    &seqbuf, &checksum);

		if (maj_stat != GSS_S_COMPLETE)
			return (FALSE);

		rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS;
		rqst->rq_xprt->xp_verf.oa_base = checksum.value;
		rqst->rq_xprt->xp_verf.oa_length = checksum.length;
	}
	return (TRUE);
}
Пример #14
0
int nfs_rpc_req2client_cred(struct svc_req *reqp, nfs_client_cred_t * pcred)
{
  /* Structure for managing basic AUTH_UNIX authentication */
  struct authunix_parms *aup = NULL;

  /* Stuff needed for managing RPCSEC_GSS */
#ifdef _HAVE_GSSAPI
  OM_uint32 maj_stat = 0;
  OM_uint32 min_stat = 0;
  struct svc_rpc_gss_data *gd = NULL;
  gss_buffer_desc oidbuff;
#endif

  if(reqp == NULL || pcred == NULL)
    return -1;

  pcred->flavor = reqp->rq_cred.oa_flavor;
  pcred->length = reqp->rq_cred.oa_length;

  switch (reqp->rq_cred.oa_flavor)
    {
    case AUTH_NONE:
      /* Do nothing... because there seems like nothing is to be done... */
      break;

    case AUTH_UNIX:
      aup = (struct authunix_parms *)(reqp->rq_clntcred);

      pcred->auth_union.auth_unix.aup_uid = aup->aup_uid;
      pcred->auth_union.auth_unix.aup_gid = aup->aup_gid;
      pcred->auth_union.auth_unix.aup_time = aup->aup_time;

      break;

#ifdef _HAVE_GSSAPI
    case RPCSEC_GSS:
      /* Extract the information from the RPCSEC_GSS opaque structure */
      gd = SVCAUTH_PRIVATE(reqp->rq_xprt->xp_auth);

      pcred->auth_union.auth_gss.svc = (unsigned int)(gd->sec.svc);
      pcred->auth_union.auth_gss.qop = (unsigned int)(gd->sec.qop);
      pcred->auth_union.auth_gss.gss_context_id = gd->ctx;
      strncpy(pcred->auth_union.auth_gss.cname, gd->cname.value, NFS_CLIENT_NAME_LEN);

      if((maj_stat = gss_oid_to_str(&min_stat, gd->sec.mech, &oidbuff)) != GSS_S_COMPLETE)
        {
          char errbuff[1024];
          log_sperror_gss(errbuff, maj_stat, min_stat);
          LogCrit(COMPONENT_DISPATCH,
                  "GSSAPI ERROR: %u|%u = %s",
                  maj_stat, min_stat, errbuff);
          return -1;
        }
      strncpy(pcred->auth_union.auth_gss.stroid, oidbuff.value, NFS_CLIENT_NAME_LEN);

      /* Je fais le menage derriere moi */
      (void)gss_release_buffer(&min_stat, &oidbuff);
      break;
#endif

    default:
      /* Unsupported authentication flavour */
      return -1;
      break;
    }

  return 1;
}                               /* nfs_rpc_req2client_cred */
Пример #15
0
/**
 *
 * get_req_uid_gid: 
 *
 * 
 *
 * @param ptr_req [IN]  incoming request.
 * @param pexport_client [IN] related export client
 * @param pexport [IN]  related export entry
 * @param user_credentials [OUT] Filled in structure with uid and gids
 * 
 * @return TRUE if successful, FALSE otherwise 
 *
 */
int get_req_uid_gid(struct svc_req *ptr_req,
                    exportlist_client_entry_t * pexport_client,
                    exportlist_t * pexport, struct user_cred *user_credentials)
{
  struct authunix_parms *punix_creds = NULL;
  unsigned int rpcxid = 0;
#ifdef _HAVE_GSSAPI
  struct svc_rpc_gss_data *gd = NULL;
  char principal[MAXNAMLEN];
#endif

  if (user_credentials == NULL)
    return FALSE;

  rpcxid = get_rpc_xid(ptr_req);

  switch (ptr_req->rq_cred.oa_flavor)
    {
    case AUTH_NONE:
      /* Nothing to be done here... */
      LogFullDebug(COMPONENT_DISPATCH,
                   "Request xid=%u has authentication AUTH_NONE",
                   rpcxid);
      break;

    case AUTH_UNIX:
      LogFullDebug(COMPONENT_DISPATCH,
                   "Request xid=%u has authentication AUTH_UNIX",
                   rpcxid);
      /* We map the rq_cred to Authunix_parms */
      punix_creds = (struct authunix_parms *)ptr_req->rq_clntcred;

      /* Get the uid/gid couple */
      user_credentials->caller_uid = punix_creds->aup_uid;
      user_credentials->caller_gid = punix_creds->aup_gid;
      user_credentials->caller_glen = punix_creds->aup_len;
      user_credentials->caller_garray = punix_creds->aup_gids;

      LogFullDebug(COMPONENT_DISPATCH, "----> Uid=%u Gid=%u",
                   (unsigned int)user_credentials->caller_uid, (unsigned int)user_credentials->caller_gid);

      break;

#ifdef _HAVE_GSSAPI
    case RPCSEC_GSS:
      LogFullDebug(COMPONENT_DISPATCH,
                   "Request xid=%u has authentication RPCSEC_GSS",
                   rpcxid);
      /* Get the gss data to process them */
      gd = SVCAUTH_PRIVATE(ptr_req->rq_xprt->xp_auth);


      if(isFullDebug(COMPONENT_RPCSEC_GSS))
        {
          OM_uint32 maj_stat = 0;
          OM_uint32 min_stat = 0;
	  char ptr[256];

          gss_buffer_desc oidbuff;

          LogFullDebug(COMPONENT_RPCSEC_GSS,
                       "----> RPCSEC_GSS svc=%u RPCSEC_GSS_SVC_NONE=%u RPCSEC_GSS_SVC_INTEGRITY=%u RPCSEC_GSS_SVC_PRIVACY=%u",
                       gd->sec.svc, RPCSEC_GSS_SVC_NONE, RPCSEC_GSS_SVC_INTEGRITY,
                       RPCSEC_GSS_SVC_PRIVACY);

          memcpy(&ptr, (void *)gd->ctx + 4, 4);
          LogFullDebug(COMPONENT_RPCSEC_GSS,
                       "----> Client=%s length=%lu  Qop=%u established=%u gss_ctx_id=%p|%p",
                       (char *)gd->cname.value, gd->cname.length, gd->established, gd->sec.qop,
                       gd->ctx, ptr);

          if((maj_stat = gss_oid_to_str(&min_stat, gd->sec.mech, &oidbuff)) != GSS_S_COMPLETE)
            {
              LogFullDebug(COMPONENT_DISPATCH, "Error in gss_oid_to_str: %u|%u",
                           maj_stat, min_stat);
            }
          else
            {
              LogFullDebug(COMPONENT_RPCSEC_GSS, "----> Client mech=%s len=%lu",
                           (char *)oidbuff.value, oidbuff.length);

              // Release the string
              (void)gss_release_buffer(&min_stat, &oidbuff); 
            }
       }

      LogFullDebug(COMPONENT_RPCSEC_GSS, "Mapping principal %s to uid/gid",
                   (char *)gd->cname.value);

      memcpy(principal, gd->cname.value, gd->cname.length);
      principal[gd->cname.length] = 0;

      /* Convert to uid */
      if(!principal2uid(principal, &user_credentials->caller_uid))
	{
          LogWarn(COMPONENT_IDMAPPER,
		  "WARNING: Could not map principal to uid; mapping principal "
		  "to anonymous uid/gid");

	  /* For compatibility with Linux knfsd, we set the uid/gid
	   * to anonymous when a name->uid mapping can't be found. */
	  user_credentials->caller_uid = pexport->anonymous_uid;
	  user_credentials->caller_gid = pexport->anonymous_gid;
	  
	  /* No alternate groups for "nobody" */
	  user_credentials->caller_glen = 0 ;
	  user_credentials->caller_garray = NULL ;

	  return TRUE;
	}

      if(uidgidmap_get(user_credentials->caller_uid, &user_credentials->caller_gid) != ID_MAPPER_SUCCESS)
        {
          LogMajor(COMPONENT_DISPATCH,
                   "FAILURE: Could not resolve uidgid map for %u",
                   user_credentials->caller_uid);
          user_credentials->caller_gid = -1;
        }
      LogFullDebug(COMPONENT_DISPATCH, "----> Uid=%u Gid=%u",
                   (unsigned int)user_credentials->caller_uid, (unsigned int)user_credentials->caller_gid);
      user_credentials->caller_glen = 0;
      user_credentials->caller_garray = 0;

      break;
#endif                          /* _USE_GSSRPC */

    default:
      LogFullDebug(COMPONENT_DISPATCH,
                   "FAILURE: Request xid=%u, has unsupported authentication %d",
                   rpcxid, ptr_req->rq_cred.oa_flavor);
      /* Reject the request for weak authentication and return to worker */
      return FALSE;

      break;
    }                           /* switch( ptr_req->rq_cred.oa_flavor ) */
  return TRUE;
}
Пример #16
0
int main(int argc, char *argv[])
{
    gss_OID_set mechs;
    OM_uint32 major, minor;
    size_t i;

    major = gss_indicate_mechs(&minor, &mechs);
    if (GSS_ERROR(major)) {
        displayStatus("gss_indicate_mechs", major, minor);
        return major;
    }

    for (i = 0; i < mechs->count; i++) {
        gss_buffer_desc oidstr = GSS_C_EMPTY_BUFFER;
        gss_buffer_desc sasl_mech_name = GSS_C_EMPTY_BUFFER;
        gss_buffer_desc mech_name = GSS_C_EMPTY_BUFFER;
        gss_buffer_desc mech_description = GSS_C_EMPTY_BUFFER;
        gss_OID oid = GSS_C_NO_OID;

        major = gss_oid_to_str(&minor, &mechs->elements[i], &oidstr);
        if (GSS_ERROR(major))
            continue;

        major = gss_inquire_saslname_for_mech(&minor, &mechs->elements[i],
                                              &sasl_mech_name, &mech_name,
                                              &mech_description);
        if (GSS_ERROR(major)) {
            gss_release_buffer(&minor, &oidstr);
            continue;
        }

        printf("-------------------------------------------------------------"
               "-----------------\n");
        printf("OID        : %.*s\n", (int)oidstr.length,
               (char *)oidstr.value);
        printf("SASL mech  : %.*s\n", (int)sasl_mech_name.length,
               (char *)sasl_mech_name.value);
        printf("Mech name  : %.*s\n", (int)mech_name.length,
               (char *)mech_name.value);
        printf("Mech desc  : %.*s\n", (int)mech_description.length,
               (char *)mech_description.value);
        dumpMechAttrs(&minor, &mechs->elements[i]);
        printf("-------------------------------------------------------------"
               "-----------------\n");

        if (GSS_ERROR(gss_inquire_mech_for_saslname(&minor, &sasl_mech_name,
                                                    &oid))) {
            displayStatus("gss_inquire_mech_for_saslname", major, minor);
        } else if (oid == GSS_C_NO_OID ||
            (oid->length != mechs->elements[i].length &&
             memcmp(oid->elements, mechs->elements[i].elements,
                    oid->length) != 0)) {
            gss_release_buffer(&minor, &oidstr);
            (void) gss_oid_to_str(&minor, oid, &oidstr);
            fprintf(stderr, "Got different OID %.*s for mechanism %.*s\n",
                    (int)oidstr.length, (char *)oidstr.value,
                    (int)sasl_mech_name.length, (char *)sasl_mech_name.value);
        }
        gss_release_buffer(&minor, &oidstr);
        gss_release_buffer(&minor, &sasl_mech_name);
        gss_release_buffer(&minor, &mech_name);
        gss_release_buffer(&minor, &mech_description);
    }

    gss_release_oid_set(&minor, &mechs);

    return GSS_ERROR(major) ? 1 : 0;
}
Пример #17
0
DWORD
VMCARESTVerifyKrbAuth(
    PVMCA_AUTHORIZATION_PARAM pAuthorization,
    PVMCA_ACCESS_TOKEN* ppAccessToken
    )
{
    DWORD dwError = 0;
    PSTR pszNegotiate = NULL;
    PSTR pszDecode = NULL;
    PSTR pszUser = NULL;
    char *pszToken = NULL;
    int nLength = 0;
    OM_uint32 major_status;
    OM_uint32 minor_status;
    gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc display_name = GSS_C_EMPTY_BUFFER;
    gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
    gss_name_t client_name = GSS_C_NO_NAME;
    static gss_OID_desc gss_spnego_mech_oid_desc =
                                 {6, (void *)"\x2b\x06\x01\x05\x05\x02"};
    static gss_OID gss_spnego_mech_oid = &gss_spnego_mech_oid_desc;
    gss_cred_id_t server_creds;

    pszNegotiate = pAuthorization->pszAuthorizationToken;
    if ( IsNullOrEmptyString(pszNegotiate) )
    {
        dwError = EACCES;
        BAIL_ON_VMREST_ERROR(dwError);
    }

    if (!strcmp(pszNegotiate,"testing"))
    // TODO: REMOVE
    // TODO: DO NOT CHECK IN
    {// Kerberos backdoor for testing
        dwError = VMCARESTMakeKrbAccessToken(ppAccessToken);
        BAIL_ON_VMREST_ERROR(dwError);
        goto cleanup;
    }
    dwError = base64_decode(
                        pszNegotiate,
                        &pszDecode,
                        &nLength
                        );
    BAIL_ON_VMREST_ERROR(dwError);

    dwError = server_acquire_creds(
                            "HTTP",
                            &gss_spnego_mech_oid_desc,
                            &server_creds
                            );
    BAIL_ON_VMREST_ERROR(dwError);

    input_token.length = nLength;
    input_token.value = pszDecode;

    major_status = gss_accept_sec_context(
                                    &minor_status,
                                    &gss_context,
                                    server_creds,
                                    &input_token,
                                    GSS_C_NO_CHANNEL_BINDINGS,
                                    &client_name,
                                    &gss_spnego_mech_oid,
                                    &output_token,
                                    NULL,
                                    NULL,
                                    NULL
                                    );

    if (GSS_ERROR(major_status) )
    {
        //TODO: insert show error
        dwError = EACCES;
        BAIL_ON_VMREST_ERROR(dwError);
    }

    if (output_token.length)
    {
        dwError = make_negotiate_token(&output_token, &pszToken);
        BAIL_ON_VMREST_ERROR(dwError);
    }

    if (major_status == GSS_S_CONTINUE_NEEDED)
    {
        OM_uint32 min2;
        gss_buffer_desc mech_msg = GSS_C_EMPTY_BUFFER;
        gss_buffer_desc gss_msg = GSS_C_EMPTY_BUFFER;
        gss_buffer_desc minor_msg = GSS_C_EMPTY_BUFFER;
        OM_uint32 msg_ctx = 0;
        PSTR pszError = NULL;

        gss_oid_to_str(&min2, gss_spnego_mech_oid, &mech_msg);
        gss_display_status(&min2, major_status, GSS_C_GSS_CODE, gss_spnego_mech_oid, &msg_ctx, &gss_msg);
        gss_display_status(&min2, minor_status, GSS_C_MECH_CODE, gss_spnego_mech_oid, &msg_ctx, &minor_msg);

        VMCAAllocateStringPrintfA(&pszError, "gss_rc[%d:%*s] mech[%*s] minor[%u:%*s]",
            major_status, (int)gss_msg.length,
            (const char *)(gss_msg.value?gss_msg.value:""),
            (int)mech_msg.length,
            (const char *)(mech_msg.value?mech_msg.value:""),
            minor_status, (int)minor_msg.length,
            (const char *)(minor_msg.value?minor_msg.value:""));

        gss_release_buffer(&min2, &mech_msg);
        gss_release_buffer(&min2, &gss_msg);
        gss_release_buffer(&min2, &minor_msg);
    }
    if (major_status == GSS_S_COMPLETE)
    {
        gss_display_name(&minor_status, client_name, &display_name, NULL);

        dwError = VMCAAllocateStringA(display_name.value, &pszUser);
        BAIL_ON_VMREST_ERROR(dwError);
    }

    dwError = VMCARESTMakeKrbAccessToken(ppAccessToken);
    BAIL_ON_VMREST_ERROR(dwError);

cleanup:
    if (pszUser)
    {
        VMCA_SAFE_FREE_MEMORY(pszUser);
    }
    return dwError;

error:
    goto cleanup;
}
Пример #18
0
static bool_t
svcauth_gss_accept_sec_context(struct svc_req *rqst,
			       struct rpc_gss_init_res *gr)
{
	struct svc_rpc_gss_data	*gd;
	struct rpc_gss_cred	*gc;
	gss_buffer_desc		 recv_tok, seqbuf;
	gss_OID			 mech;
	OM_uint32		 maj_stat = 0, min_stat = 0, ret_flags, seq;

	log_debug("in svcauth_gss_accept_context()");

	gd = SVCAUTH_PRIVATE(rqst->rq_xprt->xp_auth);
	gc = (struct rpc_gss_cred *)rqst->rq_clntcred;
	memset(gr, 0, sizeof(*gr));

	/* Deserialize arguments. */
	memset(&recv_tok, 0, sizeof(recv_tok));

	if (!svc_getargs(rqst->rq_xprt, xdr_rpc_gss_init_args,
			 (caddr_t)&recv_tok))
		return (FALSE);

	gr->gr_major = gss_accept_sec_context(&gr->gr_minor,
					      &gd->ctx,
					      svcauth_gss_creds,
					      &recv_tok,
					      GSS_C_NO_CHANNEL_BINDINGS,
					      &gd->client_name,
					      &mech,
					      &gr->gr_token,
					      &ret_flags,
					      NULL,
					      NULL);

	svc_freeargs(rqst->rq_xprt, xdr_rpc_gss_init_args, (caddr_t)&recv_tok);

	log_status("accept_sec_context", gr->gr_major, gr->gr_minor);
	if (gr->gr_major != GSS_S_COMPLETE &&
	    gr->gr_major != GSS_S_CONTINUE_NEEDED) {
		badauth(gr->gr_major, gr->gr_minor, rqst->rq_xprt);
		gd->ctx = GSS_C_NO_CONTEXT;
		goto errout;
	}
	gr->gr_ctx.value = "xxxx";
	gr->gr_ctx.length = 4;

	/* gr->gr_win = 0x00000005; ANDROS: for debugging linux kernel version...  */
	gr->gr_win = sizeof(gd->seqmask) * 8;

	/* Save client info. */
	gd->sec.mech = mech;
	gd->sec.qop = GSS_C_QOP_DEFAULT;
	gd->sec.svc = gc->gc_svc;
	gd->seq = gc->gc_seq;
	gd->win = gr->gr_win;

	if (gr->gr_major == GSS_S_COMPLETE) {
#ifdef SPKM
		/* spkm3: no src_name (anonymous) */
		if(!g_OID_equal(gss_mech_spkm3, mech)) {
#endif
		    maj_stat = gss_display_name(&min_stat, gd->client_name,
					    &gd->cname, &gd->sec.mech);
#ifdef SPKM
		}
#endif
		if (maj_stat != GSS_S_COMPLETE) {
			log_status("display_name", maj_stat, min_stat);
			goto errout;
		}
#ifdef DEBUG
#ifdef HAVE_HEIMDAL
		log_debug("accepted context for %.*s with "
			  "<mech {}, qop %d, svc %d>",
			  gd->cname.length, (char *)gd->cname.value,
			  gd->sec.qop, gd->sec.svc);
#else
		{
			gss_buffer_desc mechname;

			gss_oid_to_str(&min_stat, mech, &mechname);

			log_debug("accepted context for %.*s with "
				  "<mech %.*s, qop %d, svc %d>",
				  gd->cname.length, (char *)gd->cname.value,
				  mechname.length, (char *)mechname.value,
				  gd->sec.qop, gd->sec.svc);

			gss_release_buffer(&min_stat, &mechname);
		}
#endif
#endif /* DEBUG */
		seq = htonl(gr->gr_win);
		seqbuf.value = &seq;
		seqbuf.length = sizeof(seq);

		gss_release_buffer(&min_stat, &gd->checksum);
		maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT,
				    &seqbuf, &gd->checksum);

		if (maj_stat != GSS_S_COMPLETE) {
			goto errout;
		}


		rqst->rq_xprt->xp_verf.oa_flavor = RPCSEC_GSS;
		rqst->rq_xprt->xp_verf.oa_base = gd->checksum.value;
		rqst->rq_xprt->xp_verf.oa_length = gd->checksum.length;
	}
	return (TRUE);
errout:
	gss_release_buffer(&min_stat, &gr->gr_token);
	return (FALSE);
}
Пример #19
0
/*
 * Function: server_establish_context
 *
 * Purpose: establishses a GSS-API context as a specified service with
 * an incoming client, and returns the context handle and associated
 * client name
 *
 * Arguments:
 *
 *      s               (r) an established TCP connection to the client
 *      service_creds   (r) server credentials, from gss_acquire_cred
 *      context         (w) the established GSS-API context
 *      client_name     (w) the client's ASCII name
 *
 * Returns: 0 on success, -1 on failure
 *
 * Effects:
 *
 * Any valid client request is accepted.  If a context is established,
 * its handle is returned in context and the client name is returned
 * in client_name and 0 is returned.  If unsuccessful, an error
 * message is displayed and -1 is returned.
 */
static int
server_establish_context(int s, gss_cred_id_t server_creds,
                         gss_ctx_id_t *context, gss_buffer_t client_name,
                         OM_uint32 *ret_flags)
{
    gss_buffer_desc send_tok, recv_tok;
    gss_name_t client;
    gss_OID doid;
    OM_uint32 maj_stat, min_stat, acc_sec_min_stat;
    gss_buffer_desc oid_name;
    int     token_flags;

    if (recv_token(s, &token_flags, &recv_tok) < 0)
        return -1;

    if (recv_tok.value) {
        free(recv_tok.value);
        recv_tok.value = NULL;
    }

    if (!(token_flags & TOKEN_NOOP)) {
        if (logfile)
            fprintf(logfile, "Expected NOOP token, got %d token instead\n",
                    token_flags);
        return -1;
    }

    *context = GSS_C_NO_CONTEXT;

    if (token_flags & TOKEN_CONTEXT_NEXT) {
        do {
            if (recv_token(s, &token_flags, &recv_tok) < 0)
                return -1;

            if (verbose && logfile) {
                fprintf(logfile, "Received token (size=%d): \n",
                        (int) recv_tok.length);
                print_token(&recv_tok);
            }

            maj_stat = gss_accept_sec_context(&acc_sec_min_stat, context,
                                              server_creds, &recv_tok,
                                              GSS_C_NO_CHANNEL_BINDINGS,
                                              &client, &doid, &send_tok,
                                              ret_flags,
                                              NULL,  /* time_rec */
                                              NULL); /* del_cred_handle */

            if (recv_tok.value) {
                free(recv_tok.value);
                recv_tok.value = NULL;
            }

            if (send_tok.length != 0) {
                if (verbose && logfile) {
                    fprintf(logfile,
                            "Sending accept_sec_context token (size=%d):\n",
                            (int) send_tok.length);
                    print_token(&send_tok);
                }
                if (send_token(s, TOKEN_CONTEXT, &send_tok) < 0) {
                    if (logfile)
                        fprintf(logfile, "failure sending token\n");
                    return -1;
                }

                (void) gss_release_buffer(&min_stat, &send_tok);
            }
            if (maj_stat != GSS_S_COMPLETE
                && maj_stat != GSS_S_CONTINUE_NEEDED) {
                display_status("accepting context", maj_stat,
                               acc_sec_min_stat);
                if (*context != GSS_C_NO_CONTEXT)
                    gss_delete_sec_context(&min_stat, context,
                                           GSS_C_NO_BUFFER);
                return -1;
            }

            if (verbose && logfile) {
                if (maj_stat == GSS_S_CONTINUE_NEEDED)
                    fprintf(logfile, "continue needed...\n");
                else
                    fprintf(logfile, "\n");
                fflush(logfile);
            }
        } while (maj_stat == GSS_S_CONTINUE_NEEDED);

        /* display the flags */
        display_ctx_flags(*ret_flags);

        if (verbose && logfile) {
            maj_stat = gss_oid_to_str(&min_stat, doid, &oid_name);
            if (maj_stat != GSS_S_COMPLETE) {
                display_status("converting oid->string", maj_stat, min_stat);
                return -1;
            }
            fprintf(logfile, "Accepted connection using mechanism OID %.*s.\n",
                    (int) oid_name.length, (char *) oid_name.value);
            (void) gss_release_buffer(&min_stat, &oid_name);
        }

        maj_stat = gss_display_name(&min_stat, client, client_name, &doid);
        if (maj_stat != GSS_S_COMPLETE) {
            display_status("displaying name", maj_stat, min_stat);
            return -1;
        }
        enumerateAttributes(&min_stat, client, TRUE);
        showLocalIdentity(&min_stat, client);
        maj_stat = gss_release_name(&min_stat, &client);
        if (maj_stat != GSS_S_COMPLETE) {
            display_status("releasing name", maj_stat, min_stat);
            return -1;
        }
    } else {
        client_name->length = *ret_flags = 0;

        if (logfile)
            fprintf(logfile, "Accepted unauthenticated connection.\n");
    }

    return 0;
}