コード例 #1
0
ファイル: t_err.c プロジェクト: Akasurde/krb5
int
main(int argc, char *argv[])
{
    OM_uint32 minor, major, flags;
    gss_OID mech = &mech_krb5;
    gss_name_t tname;
    gss_buffer_desc itok, atok;
    gss_ctx_id_t ictx = GSS_C_NO_CONTEXT, actx = GSS_C_NO_CONTEXT;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s targetname\n", argv[0]);
        return 1;
    }
    tname = import_name(argv[1]);

    /* Get the initial context token. */
    flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG;
    major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ictx, tname,
                                 mech, flags, GSS_C_INDEFINITE,
                                 GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER,
                                 NULL, &itok, NULL, NULL);
    check_gsserr("gss_init_sec_context(1)", major, minor);
    assert(major == GSS_S_CONTINUE_NEEDED);

    /* Process this token into an acceptor context, then discard it. */
    major = gss_accept_sec_context(&minor, &actx, GSS_C_NO_CREDENTIAL, &itok,
                                   GSS_C_NO_CHANNEL_BINDINGS, NULL,
                                   NULL, &atok, NULL, NULL, NULL);
    check_gsserr("gss_accept_sec_context(1)", major, minor);
    (void)gss_release_buffer(&minor, &atok);
    (void)gss_delete_sec_context(&minor, &actx, NULL);

    /* Process the same token again, producing a replay error. */
    major = gss_accept_sec_context(&minor, &actx, GSS_C_NO_CREDENTIAL, &itok,
                                   GSS_C_NO_CHANNEL_BINDINGS, NULL,
                                   NULL, &atok, NULL, NULL, NULL);
    check_replay_error("gss_accept_sec_context(2)", major, minor);
    assert(atok.length != 0);

    /* Send the error token back the initiator. */
    (void)gss_release_buffer(&minor, &itok);
    major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ictx, tname,
                                 mech, flags, GSS_C_INDEFINITE,
                                 GSS_C_NO_CHANNEL_BINDINGS, &atok,
                                 NULL, &itok, NULL, NULL);
    check_replay_error("gss_init_sec_context(2)", major, minor);

    (void)gss_release_name(&minor, &tname);
    (void)gss_release_buffer(&minor, &itok);
    (void)gss_release_buffer(&minor, &atok);
    (void)gss_delete_sec_context(&minor, &ictx, NULL);
    (void)gss_delete_sec_context(&minor, &actx, NULL);
    return 0;
}
コード例 #2
0
static OM_uint32
initiator_approved(gss_name_t target_name, gss_OID mech)
{
    OM_uint32 min_stat, maj_stat;
    gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
    gss_buffer_desc out;

    maj_stat = gss_init_sec_context(&min_stat,
				    GSS_C_NO_CREDENTIAL,
				    &ctx,
				    target_name,
				    mech,
				    0,
				    GSS_C_INDEFINITE,
				    GSS_C_NO_CHANNEL_BINDINGS,
				    GSS_C_NO_BUFFER,
				    NULL,
				    &out,
				    NULL,
				    NULL);
    if (GSS_ERROR(maj_stat)) {
	gss_mg_collect_error(mech, maj_stat, min_stat);
	return GSS_S_BAD_MECH;
    }
    gss_release_buffer(&min_stat, &out);
    gss_delete_sec_context(&min_stat, &ctx, NULL);

    return GSS_S_COMPLETE;
}
コード例 #3
0
ファイル: uxgss.c プロジェクト: rdebath/sgt
Ssh_gss_stat ssh_gss_init_sec_context(Ssh_gss_ctx *ctx,
                                      Ssh_gss_name srv_name,
                                      int to_deleg,
				      Ssh_gss_buf *recv_tok,
				      Ssh_gss_buf *send_tok)
{
    uxSsh_gss_ctx *uxctx = (uxSsh_gss_ctx*) *ctx;
    OM_uint32 ret_flags;

    if (to_deleg) to_deleg = GSS_C_DELEG_FLAG;
    uxctx->maj_stat = gss_init_sec_context(&uxctx->min_stat,
					   GSS_C_NO_CREDENTIAL,
					   &uxctx->ctx,
					   srv_name,
					   (gss_OID) putty_gss_mech_krb5,
					   GSS_C_MUTUAL_FLAG |
					   GSS_C_INTEG_FLAG | to_deleg,
					   0,
					   GSS_C_NO_CHANNEL_BINDINGS,
					   recv_tok,
					   NULL,   /* ignore mech type */
					   send_tok,
					   &ret_flags,
					   NULL);  /* ignore time_rec */
  
    if (uxctx->maj_stat == GSS_S_COMPLETE) return SSH_GSS_S_COMPLETE;
    if (uxctx->maj_stat == GSS_S_CONTINUE_NEEDED) return SSH_GSS_S_CONTINUE_NEEDED;
    return SSH_GSS_FAILURE;
}
コード例 #4
0
ファイル: gss-clnt.c プロジェクト: AlfredArouna/illumos-gate
/*
 * Wrapper to init_sec_context. Requires that the context contains:
 *
 *	oid
 * 	server name (from ssh_gssapi_import_name)
 */
OM_uint32
ssh_gssapi_init_ctx(Gssctxt *ctx, const char *server_host, int deleg_creds,
		    gss_buffer_t recv_tok, gss_buffer_t send_tok)
{
	int flags = GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG;

	debug("%s(%p, %s, %d, %p, %p)", __func__, ctx, server_host,
	    deleg_creds, recv_tok, send_tok);

	if (deleg_creds) {
		flags |= GSS_C_DELEG_FLAG;
		debug("Delegating GSS-API credentials");
	}

	/* Build target principal */
	if (ctx->desired_name == GSS_C_NO_NAME &&
	    !ssh_gssapi_import_name(ctx, server_host)) {
		return (ctx->major);
	}

	ctx->major = gss_init_sec_context(&ctx->minor, GSS_C_NO_CREDENTIAL,
	    &ctx->context, ctx->desired_name, ctx->desired_mech, flags,
	    0, /* default lifetime */
	    NULL, /* no channel bindings */
	    recv_tok,
	    NULL, /* actual mech type */
	    send_tok, &ctx->flags,
	    NULL); /* actual lifetime */

	if (GSS_ERROR(ctx->major))
		ssh_gssapi_error(ctx, "calling GSS_Init_sec_context()");

	return (ctx->major);
}
コード例 #5
0
ファイル: gss-token.c プロジェクト: elric1/gss-token
static int
write_one_token(gss_name_t service, int delegate, int negotiate)
{
	gss_ctx_id_t	 ctx = GSS_C_NO_CONTEXT;
	gss_buffer_desc	 in;
	gss_buffer_desc	 out;
	OM_uint32	 maj;
	OM_uint32	 min;
	OM_uint32	 flags = 0;
	int		 ret = 0;
	char		*base64_output = NULL;

	in.length  = 0;
	in.value   = 0;
	out.length = 0;
	out.value  = 0;

	if (delegate)
		flags |= GSS_C_DELEG_FLAG;

        maj = gss_init_sec_context(&min, GSS_C_NO_CREDENTIAL, &ctx, service,
	    GSS_C_NO_OID, flags, 0, GSS_C_NO_CHANNEL_BINDINGS, &in, NULL, &out,
	    NULL, NULL);

	GBAIL("gss_init_sec_context", maj, min);

	base64_output = base64_encode(out.value, out.length);

	if (!base64_output) {
		fprintf(stderr, "Out of memory.\n");
		ret = 1;
		goto bail;
	}

	if (!nflag)
		printf("%s%s\n", negotiate?"Negotiate ":"", base64_output);

bail:
	if (out.value)
		gss_release_buffer(&min, &out);

	if (ctx != GSS_C_NO_CONTEXT) {
		/*
		 * XXXrcd: here we ignore the fact that we might have an
		 *         output token as this program doesn't do terribly
		 *         well in that case.
		 */
		gss_delete_sec_context(&min, &ctx, NULL);
	}

	free(base64_output);

	return ret;
}
コード例 #6
0
static gint
soup_gss_client_step (SoupNegotiateConnectionState *conn, const gchar *challenge, GError **err)
{
	OM_uint32 maj_stat, min_stat;
	gss_buffer_desc in = GSS_C_EMPTY_BUFFER;
	gss_buffer_desc out = GSS_C_EMPTY_BUFFER;
	gint ret = AUTH_GSS_CONTINUE;

	g_clear_pointer (&conn->response_header, g_free);

	if (challenge && *challenge) {
		size_t len;
		in.value = g_base64_decode (challenge, &len);
		in.length = len;
	}

	maj_stat = gss_init_sec_context (&min_stat,
					 GSS_C_NO_CREDENTIAL,
					 &conn->context,
					 conn->server_name,
					 (gss_OID) &gss_mech_spnego,
					 GSS_C_MUTUAL_FLAG,
					 GSS_C_INDEFINITE,
					 GSS_C_NO_CHANNEL_BINDINGS,
					 &in,
					 NULL,
					 &out,
					 NULL,
					 NULL);

	if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED)) {
		soup_gss_error (maj_stat, min_stat, err);
		ret = AUTH_GSS_ERROR;
		goto out;
	}

	ret = (maj_stat == GSS_S_COMPLETE) ? AUTH_GSS_COMPLETE : AUTH_GSS_CONTINUE;
	if (out.length) {
		gchar *response = g_base64_encode ((const guchar *) out.value, out.length);
		conn->response_header = g_strconcat ("Negotiate ", response, NULL);
		g_free (response);
		maj_stat = gss_release_buffer (&min_stat, &out);
	}

out:
	if (out.value)
		gss_release_buffer (&min_stat, &out);
	if (in.value)
		g_free (in.value);
	return ret;
}
コード例 #7
0
void initGSSAPIContext( const char *		inServiceName,
						gss_ctx_id_t * 		outContext,
						gss_buffer_desc *	outToken,
						PAPIStatus *		outStatus )
{
	gss_name_t theServiceName;

	getTargetService( inServiceName, &theServiceName, outStatus );
	if ( *outStatus == PAPISuccess )
	{
		OM_uint32		theMajorStatus;
		OM_uint32		theMinorStatus;
		gss_buffer_desc	theServiceNameBuf;
		OM_uint32		theReqFlags = GSS_C_DELEG_FLAG;
		OM_uint32		theRetFlags;
		gss_OID			theMech;
#ifdef SOLARIS
		gss_OID_desc	theMechArr =
			{ 9, "\052\206\110\206\367\022\001\002\002"};
		theMech = &theMechArr;
#else
		theMech = GSS_KRB5_MECHANISM;
#endif
		
		outToken->length = 0;
		theMajorStatus = gss_init_sec_context( &theMinorStatus,
											   GSS_C_NO_CREDENTIAL,
											   outContext,
										  	   theServiceName,
											   GSS_C_NO_OID,
											   0,
											   0,
											   NULL,
											   GSS_C_NO_BUFFER,
											   0,
											   outToken,
											   &theRetFlags,
											   0 );
		if ( theMajorStatus == GSS_S_COMPLETE )
		{
			*outStatus = PAPISuccess;
		}
		else
		{
			*outStatus = PAPIAuthenticationFailure;
		}
	}
}
コード例 #8
0
ファイル: sncgss.c プロジェクト: Aribaaa/osxsnc
uint32_t
sapgss_init_sec_context(
    uint32_t *minor_status,
    gss_cred_id_t claimant_cred_handle,
    gss_ctx_id_t *context_handle,
    gss_name_t target_name,
    sapgss_OID mech_type,
    uint32_t req_flags,
    uint32_t time_req,
    sapgss_channel_bindings_t input_chan_bindings,
    gss_buffer_t input_token,
    sapgss_OID *actual_mech_type,
    gss_buffer_t output_token,
    uint32_t *ret_flags,
    uint32_t *time_rec)
{
    gss_OID mech_type_loc, actual_mech_type_loc;
    uint32_t major_status;
    int ret;

    memset(&mech_type_loc, 0, sizeof(mech_type_loc));
    actual_mech_type_loc = NULL;
    /* Hope nobody uses these */
    if (input_chan_bindings != NULL)
	return GSS_S_FAILURE;
    ret = gss_OID_sap_to_loc(mech_type, &mech_type_loc);
    if (ret != 0) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }
    major_status = gss_init_sec_context(minor_status, claimant_cred_handle,
					context_handle, target_name,
					mech_type_loc, req_flags, time_req,
					NULL, input_token,
					&actual_mech_type_loc, output_token,
	    				ret_flags, time_rec);
    /* Comply with the gss_OID_sap_to_loc contract and free mech_type_loc */
    gss_OID_loc_release(&mech_type_loc);
    ret = gss_OID_loc_to_sap(actual_mech_type_loc, actual_mech_type);
    if (ret != 0) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }
    return major_status;
}
コード例 #9
0
ファイル: gssapi_drv.c プロジェクト: GlenWalker/egssapi
static int
init_user(gss_ctx_id_t *ctx,
	  const char *service,
	  const char *hostname,
	  gss_buffer_desc *input_token,
	  gss_buffer_desc *output_token)
{
    OM_uint32 maj_stat, min_stat;
    gss_buffer_desc name_token;
    gss_name_t server;
    const gss_OID mech_oid = GSS_C_NO_OID;

    memset(&name_token, 0, sizeof(name_token));

    name_token.length = asprintf ((char **)&name_token.value,
                                  "%s@%s", service, hostname);

    maj_stat = gss_import_name (&min_stat,
                                &name_token,
                                GSS_C_NT_HOSTBASED_SERVICE,
                                &server);

    if (GSS_ERROR(maj_stat))
        gss_err (1, min_stat,
                 "Error importing name `%s@%s':\n", service, hostname);

    maj_stat =
	gss_init_sec_context(&min_stat,
			     GSS_C_NO_CREDENTIAL,
			     ctx,
			     server,
			     mech_oid,
			     GSS_C_DELEG_FLAG,
			     0,
			     GSS_C_NO_CHANNEL_BINDINGS,
			     input_token,
			     NULL,
			     output_token,
			     NULL,
			     NULL);
    if (GSS_ERROR(maj_stat))
	gss_err (1, min_stat, "gss_init_sec_context");

    return maj_stat;
}
コード例 #10
0
ファイル: gsi.c プロジェクト: ddk50/gfarm_v2
/* this function returns 1, if an event is added */
static int
gssInitiateSecurityContextNext(
    struct gfarmGssInitiateSecurityContextState *state)
{
    OM_uint32 minStat2;
    int rv;
    static const char diag[] = "gssInitiateSecurityContextNext()";

    gfarm_mutex_lock(&gss_mutex, diag, gssDiag);
    state->majStat = gss_init_sec_context(&state->minStat,
					  state->cred,
					  &state->sc,
					  state->acceptorName,
					  GSS_C_NO_OID,
					  state->reqFlag,
					  0,
					  GSS_C_NO_CHANNEL_BINDINGS,
					  state->itPtr,
					  state->actualMechType,
					  state->otPtr,
					  &state->retFlag,
					  &state->timeRet);
    gfarm_mutex_unlock(&gss_mutex, diag, gssDiag);

    if (state->itPtr->length > 0)
	gss_release_buffer(&minStat2, state->itPtr);

    if (state->otPtr->length > 0) {
	rv = gfarm_eventqueue_add_event(state->q, state->writable, NULL);
	if (rv == 0) {
	    /* go to gfarmGssInitiateSecurityContextSendToken() */
	    return 1;
	}
	gflog_auth_error(GFARM_MSG_1000622,
	    "gfarm:gssInitiateSecurityContextNext(): %s",
			 strerror(rv));
	state->majStat = GSS_S_FAILURE;
	state->minStat = GFSL_DEFAULT_MINOR_ERROR;
    }

    return gssInitiateSecurityContextSwitch(state);
}
コード例 #11
0
ファイル: gss-genr.c プロジェクト: djmdjm/libopenssh
/*
 * Wrapper to init_sec_context
 * Requires that the context contains:
 *	oid
 *	server name (from ssh_gssapi_import_name)
 */
OM_uint32
ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok,
    gss_buffer_desc* send_tok, OM_uint32 *flags)
{
	int deleg_flag = 0;

	if (deleg_creds) {
		deleg_flag = GSS_C_DELEG_FLAG;
		debug("Delegating credentials");
	}

	ctx->major = gss_init_sec_context(&ctx->minor,
	    GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,
	    GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
	    0, NULL, recv_tok, NULL, send_tok, flags, NULL);

	if (GSS_ERROR(ctx->major))
		ssh_gssapi_error(ctx);

	return (ctx->major);
}
コード例 #12
0
ファイル: curl_gssapi.c プロジェクト: robocoder/curl
OM_uint32 Curl_gss_init_sec_context(
    struct SessionHandle *data,
    OM_uint32 *minor_status,
    gss_ctx_id_t *context,
    gss_name_t target_name,
    gss_OID mech_type,
    gss_channel_bindings_t input_chan_bindings,
    gss_buffer_t input_token,
    gss_buffer_t output_token,
    OM_uint32 *ret_flags)
{
  OM_uint32 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;

  if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) {
#ifdef GSS_C_DELEG_POLICY_FLAG
    req_flags |= GSS_C_DELEG_POLICY_FLAG;
#else
    infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not "
        "compiled in\n");
#endif
  }

  if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG)
    req_flags |= GSS_C_DELEG_FLAG;

  return gss_init_sec_context(minor_status,
                              GSS_C_NO_CREDENTIAL, /* cred_handle */
                              context,
                              target_name,
                              mech_type,
                              req_flags,
                              0, /* time_req */
                              input_chan_bindings,
                              input_token,
                              NULL, /* actual_mech_type */
                              output_token,
                              ret_flags,
                              NULL /* time_rec */);
}
コード例 #13
0
ファイル: common.c プロジェクト: PADL/krb5
void
establish_contexts(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred,
                   gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ictx,
                   gss_ctx_id_t *actx, gss_name_t *src_name, gss_OID *amech,
                   gss_cred_id_t *deleg_cred)
{
    OM_uint32 minor, imaj, amaj;
    gss_buffer_desc itok, atok;

    *ictx = *actx = GSS_C_NO_CONTEXT;
    imaj = amaj = GSS_S_CONTINUE_NEEDED;
    itok.value = atok.value = NULL;
    itok.length = atok.length = 0;
    for (;;) {
        (void)gss_release_buffer(&minor, &itok);
        imaj = gss_init_sec_context(&minor, icred, ictx, tname, imech, flags,
                                    GSS_C_INDEFINITE,
                                    GSS_C_NO_CHANNEL_BINDINGS, &atok, NULL,
                                    &itok, NULL, NULL);
        check_gsserr("gss_init_sec_context", imaj, minor);
        if (amaj == GSS_S_COMPLETE)
            break;

        (void)gss_release_buffer(&minor, &atok);
        amaj = gss_accept_sec_context(&minor, actx, acred, &itok,
                                      GSS_C_NO_CHANNEL_BINDINGS, src_name,
                                      amech, &atok, NULL, NULL, deleg_cred);
        check_gsserr("gss_accept_sec_context", amaj, minor);
        (void)gss_release_buffer(&minor, &itok);
        if (imaj == GSS_S_COMPLETE)
            break;
    }

    if (imaj != GSS_S_COMPLETE || amaj != GSS_S_COMPLETE)
        errout("One side wants to continue after the other is done");

    (void)gss_release_buffer(&minor, &itok);
    (void)gss_release_buffer(&minor, &atok);
}
コード例 #14
0
ファイル: gssapi_client.cpp プロジェクト: 5igm4/libzmq
int zmq::gssapi_client_t::initialize_context ()
{
    // First time through, import service_name into target_name
    if (target_name == GSS_C_NO_NAME) {
        send_tok.value = service_name;
        send_tok.length = strlen(service_name);
        OM_uint32 maj = gss_import_name(&min_stat, &send_tok,
                                        GSS_C_NT_HOSTBASED_SERVICE,
                                        &target_name);

        if (maj != GSS_S_COMPLETE)
            return -1;
    }

    maj_stat = gss_init_sec_context(&init_sec_min_stat, cred, &context,
                                    target_name, mechs.elements,
                                    gss_flags, 0, NULL, token_ptr, NULL,
                                    &send_tok, &ret_flags, NULL);

    if (token_ptr != GSS_C_NO_BUFFER)
        free(recv_tok.value);

    return 0;
}
コード例 #15
0
ファイル: krb5.c プロジェクト: 0w/moai-dev
static int
krb5_auth(void *app_data, struct connectdata *conn)
{
  int ret;
  char *p;
  const char *host = conn->dns_entry->addr->ai_canonname;
  ssize_t nread;
  curl_socklen_t l = sizeof(conn->local_addr);
  struct SessionHandle *data = conn->data;
  CURLcode result;
  const char *service = "ftp", *srv_host = "host";
  gss_buffer_desc gssbuf, _gssresp, *gssresp;
  OM_uint32 maj, min;
  gss_name_t gssname;
  gss_ctx_id_t *context = app_data;
  struct gss_channel_bindings_struct chan;

  if(getsockname(conn->sock[FIRSTSOCKET],
                 (struct sockaddr *)LOCAL_ADDR, &l) < 0)
    perror("getsockname()");

  chan.initiator_addrtype = GSS_C_AF_INET;
  chan.initiator_address.length = l - 4;
  chan.initiator_address.value =
    &((struct sockaddr_in *)LOCAL_ADDR)->sin_addr.s_addr;
  chan.acceptor_addrtype = GSS_C_AF_INET;
  chan.acceptor_address.length = l - 4;
  chan.acceptor_address.value =
    &((struct sockaddr_in *)REMOTE_ADDR)->sin_addr.s_addr;
  chan.application_data.length = 0;
  chan.application_data.value = NULL;

  /* this loop will execute twice (once for service, once for host) */
  while(1) {
    /* this really shouldn't be repeated here, but can't help it */
    if(service == srv_host) {
      result = Curl_ftpsendf(conn, "AUTH GSSAPI");

      if(result)
        return -2;
      if(Curl_GetFTPResponse(&nread, conn, NULL))
        return -1;

      if(data->state.buffer[0] != '3')
        return -1;
    }

    gssbuf.value = data->state.buffer;
    gssbuf.length = snprintf(gssbuf.value, BUFSIZE, "%s@%s", service, host);
    maj = gss_import_name(&min, &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &gssname);
    if(maj != GSS_S_COMPLETE) {
      gss_release_name(&min, &gssname);
      if(service == srv_host) {
        Curl_failf(data, "Error importing service name %s", gssbuf.value);
        return AUTH_ERROR;
      }
      service = srv_host;
      continue;
    }
    {
      gss_OID t;
      gss_display_name(&min, gssname, &gssbuf, &t);
      Curl_infof(data, "Trying against %s\n", gssbuf.value);
      gss_release_buffer(&min, &gssbuf);
    }
    gssresp = GSS_C_NO_BUFFER;
    *context = GSS_C_NO_CONTEXT;

    do {
      ret = AUTH_OK;
      maj = gss_init_sec_context(&min,
                                 GSS_C_NO_CREDENTIAL,
                                 context,
                                 gssname,
                                 GSS_C_NO_OID,
                                 GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
                                 0,
                                 &chan,
                                 gssresp,
                                 NULL,
                                 &gssbuf,
                                 NULL,
                                 NULL);

      if(gssresp) {
        free(_gssresp.value);
        gssresp = NULL;
      }

      if(maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) {
        Curl_infof(data, "Error creating security context");
        ret = AUTH_ERROR;
        break;
      }

      if(gssbuf.length != 0) {
        if(Curl_base64_encode(data, (char *)gssbuf.value, gssbuf.length, &p)
           < 1) {
          Curl_infof(data, "Out of memory base64-encoding");
          ret = AUTH_CONTINUE;
          break;
        }

        result = Curl_ftpsendf(conn, "ADAT %s", p);

        free(p);

        if(result) {
          ret = -2;
          break;
        }

        if(Curl_GetFTPResponse(&nread, conn, NULL)) {
          ret = -1;
          break;
        }

        if(data->state.buffer[0] != '2' && data->state.buffer[0] != '3'){
          Curl_infof(data, "Server didn't accept auth data\n");
          ret = AUTH_ERROR;
          break;
        }

        p = data->state.buffer + 4;
        p = strstr(p, "ADAT=");
        if(p) {
          _gssresp.length = Curl_base64_decode(p + 5, (unsigned char **)
                                               &_gssresp.value);
          if(_gssresp.length < 1) {
            Curl_failf(data, "Out of memory base64-encoding");
            ret = AUTH_CONTINUE;
            break;
          }
        }

        gssresp = &_gssresp;
      }
    } while(maj == GSS_S_CONTINUE_NEEDED);

    gss_release_name(&min, &gssname);

    if(gssresp)
      free(_gssresp.value);

    if(ret == AUTH_OK || service == srv_host)
      return ret;

    service = srv_host;
  }
}
コード例 #16
0
static OM_uint32
spnego_initial
           (OM_uint32 * minor_status,
	    gssspnego_cred cred,
            gss_ctx_id_t * context_handle,
            const gss_name_t target_name,
            const gss_OID mech_type,
            OM_uint32 req_flags,
            OM_uint32 time_req,
            const gss_channel_bindings_t input_chan_bindings,
            const gss_buffer_t input_token,
            gss_OID * actual_mech_type,
            gss_buffer_t output_token,
            OM_uint32 * ret_flags,
            OM_uint32 * time_rec
    )
{
    NegTokenInit ni;
    int ret;
    OM_uint32 sub, minor;
    gss_buffer_desc mech_token;
    u_char *buf;
    size_t buf_size, buf_len;
    gss_buffer_desc data;
    size_t ni_len;
    gss_ctx_id_t context;
    gssspnego_ctx ctx;
    spnego_name name = (spnego_name)target_name;

    *minor_status = 0;

    memset (&ni, 0, sizeof(ni));

    *context_handle = GSS_C_NO_CONTEXT;

    if (target_name == GSS_C_NO_NAME)
	return GSS_S_BAD_NAME;

    sub = _gss_spnego_alloc_sec_context(&minor, &context);
    if (GSS_ERROR(sub)) {
	*minor_status = minor;
	return sub;
    }
    ctx = (gssspnego_ctx)context;

    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);

    ctx->local = 1;

    sub = gss_import_name(&minor, &name->value, &name->type, &ctx->target_name);
    if (GSS_ERROR(sub)) {
	*minor_status = minor;
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return sub;
    }

    sub = _gss_spnego_indicate_mechtypelist(&minor,
					    ctx->target_name,
					    initiator_approved,
					    0,
					    cred,
					    &ni.mechTypes,
					    &ctx->preferred_mech_type);
    if (GSS_ERROR(sub)) {
	*minor_status = minor;
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return sub;
    }

    ni.reqFlags = NULL;

    /*
     * If we have a credential handle, use it to select the mechanism
     * that we will use
     */

    /* generate optimistic token */
    sub = gss_init_sec_context(&minor,
			       (cred != NULL) ? cred->negotiated_cred_id :
			          GSS_C_NO_CREDENTIAL,
			       &ctx->negotiated_ctx_id,
			       ctx->target_name,
			       ctx->preferred_mech_type,
			       req_flags,
			       time_req,
			       input_chan_bindings,
			       input_token,
			       &ctx->negotiated_mech_type,
			       &mech_token,
			       &ctx->mech_flags,
			       &ctx->mech_time_rec);
    if (GSS_ERROR(sub)) {
	free_NegTokenInit(&ni);
	*minor_status = minor;
	gss_mg_collect_error(ctx->preferred_mech_type, sub, minor);
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return sub;
    }
    if (sub == GSS_S_COMPLETE)
	ctx->maybe_open = 1;

    if (mech_token.length != 0) {
	ALLOC(ni.mechToken, 1);
	if (ni.mechToken == NULL) {
	    free_NegTokenInit(&ni);
	    gss_release_buffer(&minor, &mech_token);
	    _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	    *minor_status = ENOMEM;
	    return GSS_S_FAILURE;
	}
	ni.mechToken->length = mech_token.length;
	ni.mechToken->data = malloc(mech_token.length);
	if (ni.mechToken->data == NULL && mech_token.length != 0) {
	    free_NegTokenInit(&ni);
	    gss_release_buffer(&minor, &mech_token);
	    *minor_status = ENOMEM;
	    _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	    return GSS_S_FAILURE;
	}
	memcpy(ni.mechToken->data, mech_token.value, mech_token.length);
	gss_release_buffer(&minor, &mech_token);
    } else
	ni.mechToken = NULL;

    ni.mechListMIC = NULL;

    ni_len = length_NegTokenInit(&ni);
    buf_size = 1 + der_length_len(ni_len) + ni_len;

    buf = malloc(buf_size);
    if (buf == NULL) {
	free_NegTokenInit(&ni);
	*minor_status = ENOMEM;
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return GSS_S_FAILURE;
    }

    ret = encode_NegTokenInit(buf + buf_size - 1,
			      ni_len,
			      &ni, &buf_len);
    if (ret == 0 && ni_len != buf_len)
	abort();

    if (ret == 0) {
	size_t tmp;

	ret = der_put_length_and_tag(buf + buf_size - buf_len - 1,
				     buf_size - buf_len,
				     buf_len,
				     ASN1_C_CONTEXT,
				     CONS,
				     0,
				     &tmp);
	if (ret == 0 && tmp + buf_len != buf_size)
	    abort();
    }
    if (ret) {
	*minor_status = ret;
	free(buf);
	free_NegTokenInit(&ni);
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return GSS_S_FAILURE;
    }

    data.value  = buf;
    data.length = buf_size;

    ctx->initiator_mech_types.len = ni.mechTypes.len;
    ctx->initiator_mech_types.val = ni.mechTypes.val;
    ni.mechTypes.len = 0;
    ni.mechTypes.val = NULL;

    free_NegTokenInit(&ni);

    sub = gss_encapsulate_token(&data,
				GSS_SPNEGO_MECHANISM,
				output_token);
    free (buf);

    if (sub) {
	_gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER);
	return sub;
    }

    if (actual_mech_type)
	*actual_mech_type = ctx->negotiated_mech_type;
    if (ret_flags)
	*ret_flags = ctx->mech_flags;
    if (time_rec)
	*time_rec = ctx->mech_time_rec;

    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);

    *context_handle = context;

    return GSS_S_CONTINUE_NEEDED;
}
コード例 #17
0
static OM_uint32
spnego_reply
           (OM_uint32 * minor_status,
	    const gssspnego_cred cred,
            gss_ctx_id_t * context_handle,
            const gss_name_t target_name,
            const gss_OID mech_type,
            OM_uint32 req_flags,
            OM_uint32 time_req,
            const gss_channel_bindings_t input_chan_bindings,
            const gss_buffer_t input_token,
            gss_OID * actual_mech_type,
            gss_buffer_t output_token,
            OM_uint32 * ret_flags,
            OM_uint32 * time_rec
    )
{
    OM_uint32 ret, minor;
    NegotiationToken resp;
    gss_OID_desc mech;
    int require_mic;
    size_t buf_len;
    gss_buffer_desc mic_buf, mech_buf;
    gss_buffer_desc mech_output_token;
    gssspnego_ctx ctx;

    *minor_status = 0;

    ctx = (gssspnego_ctx)*context_handle;

    output_token->length = 0;
    output_token->value  = NULL;

    mech_output_token.length = 0;
    mech_output_token.value = NULL;

    mech_buf.value = NULL;
    mech_buf.length = 0;

    ret = decode_NegotiationToken(input_token->value, input_token->length,
				  &resp, NULL);
    if (ret)
      return ret;

    if (resp.element != choice_NegotiationToken_negTokenResp) {
	free_NegotiationToken(&resp);
	*minor_status = 0;
	return GSS_S_BAD_MECH;
    }

    if (resp.u.negTokenResp.negResult == NULL
	|| *(resp.u.negTokenResp.negResult) == reject
	/* || resp.u.negTokenResp.supportedMech == NULL */
	)
    {
	free_NegotiationToken(&resp);
	return GSS_S_BAD_MECH;
    }

    /*
     * Pick up the mechanism that the acceptor selected, only allow it
     * to be sent in packet.
     */

    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);

    if (resp.u.negTokenResp.supportedMech) {

	if (ctx->oidlen) {
	    free_NegotiationToken(&resp);
	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
	    return GSS_S_BAD_MECH;
	}
	ret = der_put_oid(ctx->oidbuf + sizeof(ctx->oidbuf) - 1,
			  sizeof(ctx->oidbuf),
			  resp.u.negTokenResp.supportedMech,
			  &ctx->oidlen);
	/* Avoid recursively embedded SPNEGO */
	if (ret || (ctx->oidlen == GSS_SPNEGO_MECHANISM->length &&
		    memcmp(ctx->oidbuf + sizeof(ctx->oidbuf) - ctx->oidlen,
			   GSS_SPNEGO_MECHANISM->elements,
			   ctx->oidlen) == 0))
	{
	    free_NegotiationToken(&resp);
	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
	    return GSS_S_BAD_MECH;
	}

	/* check if the acceptor took our optimistic token */
	if (ctx->oidlen != ctx->preferred_mech_type->length ||
	    memcmp(ctx->oidbuf + sizeof(ctx->oidbuf) - ctx->oidlen,
		   ctx->preferred_mech_type->elements,
		   ctx->oidlen) != 0)
	{
	    gss_delete_sec_context(&minor, &ctx->negotiated_ctx_id,
				   GSS_C_NO_BUFFER);
	    ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT;
	}
    } else if (ctx->oidlen == 0) {
	free_NegotiationToken(&resp);
	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
	return GSS_S_BAD_MECH;
    }

    /* if a token (of non zero length), or no context, pass to underlaying mech */
    if ((resp.u.negTokenResp.responseToken != NULL && resp.u.negTokenResp.responseToken->length) ||
	ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
	gss_buffer_desc mech_input_token;

	if (resp.u.negTokenResp.responseToken) {
	    mech_input_token.length = resp.u.negTokenResp.responseToken->length;
	    mech_input_token.value  = resp.u.negTokenResp.responseToken->data;
	} else {
	    mech_input_token.length = 0;
	    mech_input_token.value = NULL;
	}


	mech.length = ctx->oidlen;
	mech.elements = ctx->oidbuf + sizeof(ctx->oidbuf) - ctx->oidlen;

	/* Fall through as if the negotiated mechanism
	   was requested explicitly */
	ret = gss_init_sec_context(&minor,
				   (cred != NULL) ? cred->negotiated_cred_id :
				       GSS_C_NO_CREDENTIAL,
				   &ctx->negotiated_ctx_id,
				   ctx->target_name,
				   &mech,
				   req_flags,
				   time_req,
				   input_chan_bindings,
				   &mech_input_token,
				   &ctx->negotiated_mech_type,
				   &mech_output_token,
				   &ctx->mech_flags,
				   &ctx->mech_time_rec);
	if (GSS_ERROR(ret)) {
	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
	    free_NegotiationToken(&resp);
	    gss_mg_collect_error(&mech, ret, minor);
	    *minor_status = minor;
	    return ret;
	}
	if (ret == GSS_S_COMPLETE) {
	    ctx->open = 1;
	}
    } else if (*(resp.u.negTokenResp.negResult) == accept_completed) {
	if (ctx->maybe_open)
	    ctx->open = 1;
    }

    if (*(resp.u.negTokenResp.negResult) == request_mic) {
	ctx->require_mic = 1;
    }

    if (ctx->open) {
	/*
	 * Verify the mechListMIC if one was provided or CFX was
	 * used and a non-preferred mechanism was selected
	 */
	if (resp.u.negTokenResp.mechListMIC != NULL) {
	    require_mic = 1;
	} else {
	    ret = _gss_spnego_require_mechlist_mic(minor_status, ctx,
						   &require_mic);
	    if (ret) {
		HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
		free_NegotiationToken(&resp);
		gss_release_buffer(&minor, &mech_output_token);
		return ret;
	    }
	}
    } else {
	require_mic = 0;
    }

    if (require_mic) {
	ASN1_MALLOC_ENCODE(MechTypeList, mech_buf.value, mech_buf.length,
			   &ctx->initiator_mech_types, &buf_len, ret);
	if (ret) {
	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
	    free_NegotiationToken(&resp);
	    gss_release_buffer(&minor, &mech_output_token);
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}
	if (mech_buf.length != buf_len)
	    abort();

	if (resp.u.negTokenResp.mechListMIC == NULL) {
	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
	    free(mech_buf.value);
	    free_NegotiationToken(&resp);
	    *minor_status = 0;
	    return GSS_S_DEFECTIVE_TOKEN;
	}
	mic_buf.length = resp.u.negTokenResp.mechListMIC->length;
	mic_buf.value  = resp.u.negTokenResp.mechListMIC->data;

	if (mech_output_token.length == 0) {
	    ret = gss_verify_mic(minor_status,
				 ctx->negotiated_ctx_id,
				 &mech_buf,
				 &mic_buf,
				 NULL);
	   if (ret) {
		HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
		free(mech_buf.value);
		gss_release_buffer(&minor, &mech_output_token);
		free_NegotiationToken(&resp);
		return GSS_S_DEFECTIVE_TOKEN;
	    }
	    ctx->verified_mic = 1;
	}
    }

    ret = spnego_reply_internal(minor_status, ctx,
				require_mic ? &mech_buf : NULL,
				&mech_output_token,
				output_token);

    if (mech_buf.value != NULL)
	free(mech_buf.value);

    free_NegotiationToken(&resp);
    gss_release_buffer(&minor, &mech_output_token);

    if (actual_mech_type)
	*actual_mech_type = ctx->negotiated_mech_type;
    if (ret_flags)
	*ret_flags = ctx->mech_flags;
    if (time_rec)
	*time_rec = ctx->mech_time_rec;

    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
    return ret;
}
コード例 #18
0
ファイル: gsstunnel.c プロジェクト: frenche/gss-tunnel
static int tunnel(struct gt_service *svc, int fd, struct sockaddr *cliaddr)
{
    AUTOCLEAN(char *tmbuf, autofreestr) = NULL;
    AUTOCLEAN(struct addrinfo *addr, autofreeaddrinfo) = NULL;
    AUTOCLEAN(int sd, autofreesocket) = -1;
    AUTOCLEAN(int efd, autofreesocket) = -1;
    AUTOCLEAN(gss_name_t name, autofreegssname) = GSS_C_NO_NAME;
    AUTOCLEAN(gss_name_t srcname, autofreegssname) = GSS_C_NO_NAME;
    AUTOCLEAN(gss_cred_id_t cred, autofreegsscred) = GSS_C_NO_CREDENTIAL;
    AUTOCLEAN(gss_ctx_id_t ctx, autofreegssctx) = GSS_C_NO_CONTEXT;
    AUTOCLEAN(gss_buffer_desc output, autofreegssbuf) = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc  namebuf;
    OM_uint32 maj, min;
    OM_uint32 ignore;
    struct epoll_event events[MAX_EVENTS];
    size_t tmlen;
    int pfd; /* plain text fd */
    int cfd; /* cipher text fd */
    int ret;

    /* We allocate a 1 MiB buffer for messages, that's also the maximum msg
     * size */
    tmbuf = malloc(MAX_MSG_SIZE);
    if (!tmbuf) return ENOMEM;

    if (svc->exec) {
        fprintf(stderr, "[%s] EXEC option not supported yet, sorry!\n",
                        svc->name);
        return ENOTSUP;
    }

    ret = string_to_addrinfo(svc->connect, &addr);
    if (ret) return ret;

    errno = 0;
    sd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
    if (sd == -1) return errno;

    ret = connect(sd, addr->ai_addr, addr->ai_addrlen);
    if (ret != 0) {
        ret = errno;
        fprintf(stderr, "[%s] Failed to connect to server '%s': %s\n",
                        svc->name, svc->connect, strerror(ret));
        return ret;
    }

    if (svc->target_name) {
        namebuf.length = strlen(svc->target_name);
        namebuf.value = svc->target_name;
        maj = gss_import_name(&min, &namebuf,
                              GSS_C_NT_HOSTBASED_SERVICE, &name);
        if (maj != GSS_S_COMPLETE) {
            fprintf(stderr, "[%s] Failed to import name: '%s' (%d/%d)\n",
                            svc->name, svc->target_name,
                            (int)maj, (int)min);
            return EINVAL;
        }
    }

    if (svc->client) {
        pfd = fd;
        cfd = sd;

        do {
            maj = gss_init_sec_context(&min, cred, &ctx, name, GSS_C_NO_OID,
                                       GSS_C_MUTUAL_FLAG
                                        | GSS_C_REPLAY_FLAG
                                        | GSS_C_SEQUENCE_FLAG
                                        | GSS_C_CONF_FLAG
                                        | GSS_C_INTEG_FLAG, 0,
                                       GSS_C_NO_CHANNEL_BINDINGS,
                                       &input, NULL, &output, NULL, NULL);

            if (maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) {
                gt_gss_error(svc->name, GSS_C_NO_OID, maj, min);
                return EBADE;
            }

            if (output.length > MAX_MSG_SIZE) return ENOSPC;
            if (output.length > 0) {
                memcpy(tmbuf, output.value, output.length);
                tmlen = output.length;
                (void)gss_release_buffer(&ignore, &output);

                ret = send_msg(cfd, tmbuf, tmlen, true);
                if (ret) return ret;
            }

            if (maj == GSS_S_CONTINUE_NEEDED) {
                tmlen = MAX_MSG_SIZE;
                ret = recv_msg(cfd, tmbuf, &tmlen, true);
                if (ret) return ret;

                input.value = tmbuf;
                input.length = tmlen;
            }

        } while (maj == GSS_S_CONTINUE_NEEDED);

    } else {
        pfd = sd;
        cfd = fd;

        if (name != GSS_C_NO_NAME) {
            maj = gss_acquire_cred(&min, name, GSS_C_INDEFINITE,
                                   GSS_C_NO_OID_SET, GSS_C_ACCEPT,
                                   &cred, NULL, NULL);
            if (maj != GSS_S_COMPLETE) {
                fprintf(stderr,
                        "[%s] Failed to acquire creds for '%s' (%d/%d)\n",
                        svc->name, svc->target_name?svc->target_name:"",
                        (int)maj, (int)min);
                return EIO;
            }
        }

        do {
            tmlen = MAX_MSG_SIZE;
            ret = recv_msg(cfd, tmbuf, &tmlen, true);
            if (ret) return ret;

            input.value = tmbuf;
            input.length = tmlen;

            maj = gss_accept_sec_context(&min, &ctx, cred, &input,
                                         GSS_C_NO_CHANNEL_BINDINGS, &srcname,
                                         NULL, &output, NULL, NULL, NULL);

            if (maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) {
                gt_gss_error(svc->name, GSS_C_NO_OID, maj, min);
                return EBADE;
            }

            if (output.length > MAX_MSG_SIZE) return ENOSPC;
            if (output.length > 0) {
                memcpy(tmbuf, output.value, output.length);
                tmlen = output.length;
                (void)gss_release_buffer(&ignore, &output);

                ret = send_msg(cfd, tmbuf, tmlen, true);
                if (ret) return ret;
            }

        } while (maj == GSS_S_CONTINUE_NEEDED);
    }

    /* negotiation completed, now handle traffic */

    ret = init_epoll(cfd, pfd, &efd);
    if (ret) return ret;

    while (efd != -1) {
        struct epoll_event *ev;
        int n;
        n = epoll_wait(efd, events, MAX_EVENTS, -1);
        if (n == -1) {
            ret = errno;
            if (ret == EINTR) continue;
            return ret;
        }
        for (int i = 0; i < n; i++) {
            ev = &events[i];
            if (ev->events & (EPOLLERR|EPOLLHUP)) {
                /* one of the peers gave up */
                return ENOLINK;
            }

            /* RECEIVE */

            tmlen = MAX_MSG_SIZE;
            ret = recv_msg(ev->data.fd, tmbuf, &tmlen, (ev->data.fd == cfd));
            if (ret) return ret;

            if (ev->data.fd == cfd) {
                /* sender encrypts */
                input.value = tmbuf;
                input.length = tmlen;
                maj = gss_unwrap(&min, ctx, &input, &output, NULL, NULL);
                if (maj != GSS_S_COMPLETE) {
                    gt_gss_error(svc->name, GSS_C_NO_OID, maj, min);
                    return EIO;
                }
                if (output.length > MAX_MSG_SIZE) return ENOSPC;
                memcpy(tmbuf, output.value, output.length);
                tmlen = output.length;
                (void)gss_release_buffer(&ignore, &output);
            }

            /* RESEND */
            if (ev->data.fd == pfd) {
                /* receiver encrypts */
                input.value = tmbuf;
                input.length = tmlen;
                maj = gss_wrap(&min, ctx, 1, 0, &input, NULL, &output);
                if (maj != GSS_S_COMPLETE) {
                    gt_gss_error(svc->name, GSS_C_NO_OID, maj, min);
                    return EIO;
                }
                if (output.length > MAX_MSG_SIZE) return ENOSPC;
                memcpy(tmbuf, output.value, output.length);
                tmlen = output.length;
                (void)gss_release_buffer(&ignore, &output);
            }

            /* send to the other fd, add header only if we encrypted */
            ret = send_msg((ev->data.fd == pfd)?cfd:pfd,
                           tmbuf, tmlen, (ev->data.fd == pfd));
            if (ret) return ret;
        }
    }

    return 0;
}
コード例 #19
0
ファイル: fe-auth.c プロジェクト: cbbrowne/postgres
/*
 * Continue GSS authentication with next token as needed.
 */
static int
pg_GSS_continue(PGconn *conn)
{
	OM_uint32	maj_stat,
				min_stat,
				lmin_s;

	maj_stat = gss_init_sec_context(&min_stat,
									GSS_C_NO_CREDENTIAL,
									&conn->gctx,
									conn->gtarg_nam,
									GSS_C_NO_OID,
									GSS_C_MUTUAL_FLAG,
									0,
									GSS_C_NO_CHANNEL_BINDINGS,
		  (conn->gctx == GSS_C_NO_CONTEXT) ? GSS_C_NO_BUFFER : &conn->ginbuf,
									NULL,
									&conn->goutbuf,
									NULL,
									NULL);

	if (conn->gctx != GSS_C_NO_CONTEXT)
	{
		free(conn->ginbuf.value);
		conn->ginbuf.value = NULL;
		conn->ginbuf.length = 0;
	}

	if (conn->goutbuf.length != 0)
	{
		/*
		 * GSS generated data to send to the server. We don't care if it's the
		 * first or subsequent packet, just send the same kind of password
		 * packet.
		 */
		if (pqPacketSend(conn, 'p',
						 conn->goutbuf.value, conn->goutbuf.length)
			!= STATUS_OK)
		{
			gss_release_buffer(&lmin_s, &conn->goutbuf);
			return STATUS_ERROR;
		}
	}
	gss_release_buffer(&lmin_s, &conn->goutbuf);

	if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
	{
		pg_GSS_error(libpq_gettext("GSSAPI continuation error"),
					 conn,
					 maj_stat, min_stat);
		gss_release_name(&lmin_s, &conn->gtarg_nam);
		if (conn->gctx)
			gss_delete_sec_context(&lmin_s, &conn->gctx, GSS_C_NO_BUFFER);
		return STATUS_ERROR;
	}

	if (maj_stat == GSS_S_COMPLETE)
		gss_release_name(&lmin_s, &conn->gtarg_nam);

	return STATUS_OK;
}
コード例 #20
0
ファイル: sasl.c プロジェクト: Alexander--/samba
/* this performs a SASL/gssapi bind
   we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
   is very dependent on correctly configured DNS whereas
   this routine is much less fragile
   see RFC2078 and RFC2222 for details
*/
static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
{
	uint32_t minor_status;
	gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL;
	gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
	gss_OID mech_type = GSS_C_NULL_OID;
	gss_buffer_desc output_token, input_token;
	uint32_t req_flags, ret_flags;
	int conf_state;
	struct berval cred;
	struct berval *scred = NULL;
	int i=0;
	int gss_rc, rc;
	uint8_t *p;
	uint32_t max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
	uint8_t wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
	ADS_STATUS status;
	struct ads_saslwrap *wrap = &ads->ldap_wrap_data;

	input_token.value = NULL;
	input_token.length = 0;

	status = ads_init_gssapi_cred(ads, &gss_cred);
	if (!ADS_ERR_OK(status)) {
		goto failed;
	}

	/*
	 * Note: here we always ask the gssapi for sign and seal
	 *       as this is negotiated later after the mutal
	 *       authentication
	 */
	req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;

	for (i=0; i < MAX_GSS_PASSES; i++) {
		gss_rc = gss_init_sec_context(&minor_status,
					  gss_cred,
					  &context_handle,
					  serv_name,
					  mech_type,
					  req_flags,
					  0,
					  NULL,
					  &input_token,
					  NULL,
					  &output_token,
					  &ret_flags,
					  NULL);
		if (scred) {
			ber_bvfree(scred);
			scred = NULL;
		}
		if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
			status = ADS_ERROR_GSS(gss_rc, minor_status);
			goto failed;
		}

		cred.bv_val = (char *)output_token.value;
		cred.bv_len = output_token.length;

		rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL, 
				      &scred);
		if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
			status = ADS_ERROR(rc);
			goto failed;
		}

		if (output_token.value) {
			gss_release_buffer(&minor_status, &output_token);
		}

		if (scred) {
			input_token.value = scred->bv_val;
			input_token.length = scred->bv_len;
		} else {
			input_token.value = NULL;
			input_token.length = 0;
		}

		if (gss_rc == 0) break;
	}

	gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token,
			    &conf_state,NULL);
	if (scred) {
		ber_bvfree(scred);
		scred = NULL;
	}
	if (gss_rc) {
		status = ADS_ERROR_GSS(gss_rc, minor_status);
		goto failed;
	}

	p = (uint8_t *)output_token.value;

#if 0
	file_save("sasl_gssapi.dat", output_token.value, output_token.length);
#endif

	if (p) {
		wrap_type = CVAL(p,0);
		SCVAL(p,0,0);
		max_msg_size = RIVAL(p,0);
	}

	gss_release_buffer(&minor_status, &output_token);

	if (!(wrap_type & wrap->wrap_type)) {
		/*
		 * the server doesn't supports the wrap
		 * type we want :-(
		 */
		DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
			wrap->wrap_type, wrap_type));
		DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
		status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
		goto failed;
	}

	/* 0x58 is the minimum windows accepts */
	if (max_msg_size < 0x58) {
		max_msg_size = 0x58;
	}

	output_token.length = 4;
	output_token.value = SMB_MALLOC(output_token.length);
	if (!output_token.value) {
		output_token.length = 0;
		status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
		goto failed;
	}
	p = (uint8_t *)output_token.value;

	RSIVAL(p,0,max_msg_size);
	SCVAL(p,0,wrap->wrap_type);

	/*
	 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
	 * but using ads->config.bind_path is the wrong! It should be
	 * the DN of the user object!
	 *
	 * w2k3 gives an error when we send an incorrect DN, but sending nothing
	 * is ok and matches the information flow used in GSS-SPNEGO.
	 */

	gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
			&output_token, /* used as *input* here. */
			&conf_state,
			&input_token); /* Used as *output* here. */
	if (gss_rc) {
		status = ADS_ERROR_GSS(gss_rc, minor_status);
		output_token.length = 0;
		SAFE_FREE(output_token.value);
		goto failed;
	}

	/* We've finished with output_token. */
	SAFE_FREE(output_token.value);
	output_token.length = 0;

	cred.bv_val = (char *)input_token.value;
	cred.bv_len = input_token.length;

	rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL, 
			      &scred);
	gss_release_buffer(&minor_status, &input_token);
	status = ADS_ERROR(rc);
	if (!ADS_ERR_OK(status)) {
		goto failed;
	}

	if (wrap->wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
		gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
					     (wrap->wrap_type == ADS_SASLWRAP_TYPE_SEAL),
					     GSS_C_QOP_DEFAULT,
					     max_msg_size, &wrap->out.max_unwrapped);
		if (gss_rc) {
			status = ADS_ERROR_GSS(gss_rc, minor_status);
			goto failed;
		}

		wrap->out.sig_size = max_msg_size - wrap->out.max_unwrapped;
		wrap->in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
		wrap->in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
		status = ads_setup_sasl_wrapping(wrap->wrap_private_data, ads->ldap.ld,
						 &ads_sasl_gssapi_ops,
						 context_handle);
		if (!ADS_ERR_OK(status)) {
			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
				ads_errstr(status)));
			goto failed;
		}
		/* make sure we don't free context_handle */
		context_handle = GSS_C_NO_CONTEXT;
	}

failed:
	if (gss_cred != GSS_C_NO_CREDENTIAL)
		gss_release_cred(&minor_status, &gss_cred);
	if (context_handle != GSS_C_NO_CONTEXT)
		gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);

	if(scred)
		ber_bvfree(scred);
	return status;
}
コード例 #21
0
ファイル: dnsgss.c プロジェクト: amitay/samba
static DNS_ERROR dns_negotiate_gss_ctx_int( TALLOC_CTX *mem_ctx,
					    struct dns_connection *conn,
					    const char *keyname,
					    const gss_name_t target_name,
					    gss_ctx_id_t *ctx, 
					    enum dns_ServerType srv_type )
{
	struct gss_buffer_desc_struct input_desc, *input_ptr, output_desc;
	OM_uint32 major, minor;
	OM_uint32 ret_flags;
	DNS_ERROR err;

	gss_OID_desc krb5_oid_desc =
		{ 9, (const char *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };

	*ctx = GSS_C_NO_CONTEXT;
	input_ptr = NULL;

	do {
		major = gss_init_sec_context(
			&minor, NULL, ctx, target_name, &krb5_oid_desc,
			GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG |
			GSS_C_CONF_FLAG |
			GSS_C_INTEG_FLAG,
			0, NULL, input_ptr, NULL, &output_desc,
			&ret_flags, NULL );

		if (input_ptr != NULL) {
			TALLOC_FREE(input_desc.value);
		}

		if (output_desc.length != 0) {

			struct dns_request *req;
			struct dns_rrec *rec;
			struct dns_buffer *buf;

			time_t t = time(NULL);

			err = dns_create_query(mem_ctx, keyname, QTYPE_TKEY,
					       DNS_CLASS_IN, &req);
			if (!ERR_DNS_IS_OK(err)) goto error;

			err = dns_create_tkey_record(
				req, keyname, "gss.microsoft.com", t,
				t + 86400, DNS_TKEY_MODE_GSSAPI, 0,
				output_desc.length, (uint8 *)output_desc.value,
				&rec );
			if (!ERR_DNS_IS_OK(err)) goto error;

			/* Windows 2000 DNS is broken and requires the
			   TKEY payload in the Answer section instead
			   of the Additional seciton like Windows 2003 */

			if ( srv_type == DNS_SRV_WIN2000 ) {
				err = dns_add_rrec(req, rec, &req->num_answers,
						   &req->answers);
			} else {
				err = dns_add_rrec(req, rec, &req->num_additionals,
						   &req->additionals);
			}
			
			if (!ERR_DNS_IS_OK(err)) goto error;

			err = dns_marshall_request(req, req, &buf);
			if (!ERR_DNS_IS_OK(err)) goto error;

			err = dns_send(conn, buf);
			if (!ERR_DNS_IS_OK(err)) goto error;

			TALLOC_FREE(req);
		}

		gss_release_buffer(&minor, &output_desc);

		if ((major != GSS_S_COMPLETE) &&
		    (major != GSS_S_CONTINUE_NEEDED)) {
			return ERROR_DNS_GSS_ERROR;
		}

		if (major == GSS_S_CONTINUE_NEEDED) {

			struct dns_request *resp;
			struct dns_buffer *buf;
			struct dns_tkey_record *tkey;

			err = dns_receive(mem_ctx, conn, &buf);
			if (!ERR_DNS_IS_OK(err)) goto error;

			err = dns_unmarshall_request(buf, buf, &resp);
			if (!ERR_DNS_IS_OK(err)) goto error;

			/*
			 * TODO: Compare id and keyname
			 */
			
			if ((resp->num_additionals != 1) ||
			    (resp->num_answers == 0) ||
			    (resp->answers[0]->type != QTYPE_TKEY)) {
				err = ERROR_DNS_INVALID_MESSAGE;
				goto error;
			}

			err = dns_unmarshall_tkey_record(
				mem_ctx, resp->answers[0], &tkey);
			if (!ERR_DNS_IS_OK(err)) goto error;

			input_desc.length = tkey->key_length;
			input_desc.value = talloc_move(mem_ctx, &tkey->key);

			input_ptr = &input_desc;

			TALLOC_FREE(buf);
		}

	} while ( major == GSS_S_CONTINUE_NEEDED );

	/* If we arrive here, we have a valid security context */

	err = ERROR_DNS_SUCCESS;

      error:

	return err;
}
コード例 #22
0
ファイル: ne_auth.c プロジェクト: elambert/honeycomb
/* Continue a GSS-API Negotiate exchange, using input TOKEN if
 * non-NULL.  Returns non-zero on error. */
static int continue_negotiate(auth_session *sess, const char *token)
{
    unsigned int major, minor;
    gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
    unsigned char *bintoken = NULL;
    int ret;

    if (token) {
        input.length = ne_unbase64(token, &bintoken);
        if (input.length == 0) {
            NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Invalid input [%s].\n",
                     token);
            return -1;
        }
        input.value = bintoken;
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Continuation token [%s]\n", token);
    }
    else if (sess->gssctx != GSS_C_NO_CONTEXT) {
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Reset incomplete context.\n");
        gss_delete_sec_context(&minor, &sess->gssctx, GSS_C_NO_BUFFER);
    }

    major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &sess->gssctx,
                                 sess->gssname, sess->gssmech, 
                                 GSS_C_MUTUAL_FLAG, GSS_C_INDEFINITE, 
                                 GSS_C_NO_CHANNEL_BINDINGS,
                                 &input, &sess->gssmech, &output, NULL, NULL);

    /* done with the input token. */
    if (bintoken) ne_free(bintoken);

    if (GSS_ERROR(major)) {
        ne_buffer *err = ne_buffer_create();
        int flag = 0;

        make_gss_error(err, &flag, major, GSS_C_GSS_CODE);
        make_gss_error(err, &flag, minor, GSS_C_MECH_CODE);
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Error: %s\n", err->data);
        ne_set_error(sess->sess, _("GSSAPI authentication error (%s)"), 
                     err->data);
        ne_buffer_destroy(err);
        return -1;
    }

    if (major == GSS_S_CONTINUE_NEEDED || major == GSS_S_COMPLETE) {
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: init_sec_context OK. (major=%d)\n",
                 major);
        ret = 0;
    } 
    else {
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Init failure %d.\n", major);
        ret = -1;
    }

    if (major != GSS_S_CONTINUE_NEEDED) {
        /* context no longer needed: destroy it */
        gss_delete_sec_context(&minor, &sess->gssctx, GSS_C_NO_BUFFER);
    }

    if (output.length) {
        sess->gssapi_token = ne_base64(output.value, output.length);
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Output token: [%s]\n", 
                 sess->gssapi_token);
        gss_release_buffer(&minor, &output);
    } else {
        NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: No output token.\n");
    }

    return ret;
}
コード例 #23
0
ファイル: http_negotiate.c プロジェクト: syntheticpp/CMakeLua
int Curl_input_negotiate(struct connectdata *conn, char *header)
{
  struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
  OM_uint32 major_status, minor_status, minor_status2;
  gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
  gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
  int ret;
  size_t len;
  bool gss;
  const char* protocol;

  while(*header && ISSPACE(*header))
    header++;
  if(checkprefix("GSS-Negotiate", header)) {
    protocol = "GSS-Negotiate";
    gss = TRUE;
  }
  else if (checkprefix("Negotiate", header)) {
    protocol = "Negotiate";
    gss = FALSE;
  }
  else
    return -1;

  if (neg_ctx->context) {
    if (neg_ctx->gss != gss) {
      return -1;
    }
  }
  else {
    neg_ctx->protocol = protocol;
    neg_ctx->gss = gss;
  }

  if (neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
    /* We finished succesfully our part of authentication, but server
     * rejected it (since we're again here). Exit with an error since we
     * can't invent anything better */
    Curl_cleanup_negotiate(conn->data);
    return -1;
  }

  if (neg_ctx->server_name == NULL &&
      (ret = get_gss_name(conn, &neg_ctx->server_name)))
    return ret;

  header += strlen(neg_ctx->protocol);
  while(*header && ISSPACE(*header))
    header++;

  len = strlen(header);
  if (len > 0) {
    int rawlen = Curl_base64_decode(header, (unsigned char **)&input_token.value);
    if (rawlen < 0)
      return -1;
    input_token.length = rawlen;

#ifdef HAVE_SPNEGO /* Handle SPNEGO */
    if (checkprefix("Negotiate", header)) {
        ASN1_OBJECT *   object            = NULL;
        int             rc                = 1;
        unsigned char * spnegoToken       = NULL;
        size_t          spnegoTokenLength = 0;
        unsigned char * mechToken         = NULL;
        size_t          mechTokenLength   = 0;

        spnegoToken = malloc(input_token.length);
        if (input_token.value == NULL)
          return ENOMEM;
        spnegoTokenLength = input_token.length;

        object = OBJ_txt2obj ("1.2.840.113554.1.2.2", 1);
        if (!parseSpnegoTargetToken(spnegoToken,
                                    spnegoTokenLength,
                                    NULL,
                                    NULL,
                                    &mechToken,
                                    &mechTokenLength,
                                    NULL,
                                    NULL)) {
          free(spnegoToken);
          spnegoToken = NULL;
          infof(conn->data, "Parse SPNEGO Target Token failed\n");
        }
        else {
          free(input_token.value);
          input_token.value = NULL;
          input_token.value = malloc(mechTokenLength);
          memcpy(input_token.value, mechToken,mechTokenLength);
          input_token.length = mechTokenLength;
          free(mechToken);
          mechToken = NULL;
          infof(conn->data, "Parse SPNEGO Target Token succeeded\n");
        }
    }
#endif
  }

  major_status = gss_init_sec_context(&minor_status,
                                      GSS_C_NO_CREDENTIAL,
                                      &neg_ctx->context,
                                      neg_ctx->server_name,
                                      GSS_C_NO_OID,
                                      GSS_C_DELEG_FLAG,
                                      0,
                                      GSS_C_NO_CHANNEL_BINDINGS,
                                      &input_token,
                                      NULL,
                                      &output_token,
                                      NULL,
                                      NULL);
  if (input_token.length > 0)
    gss_release_buffer(&minor_status2, &input_token);
  neg_ctx->status = major_status;
  if (GSS_ERROR(major_status)) {
    /* Curl_cleanup_negotiate(conn->data) ??? */
    log_gss_error(conn, minor_status,
                  (char *)"gss_init_sec_context() failed: ");
    return -1;
  }

  if (output_token.length == 0) {
    return -1;
  }

  neg_ctx->output_token = output_token;
  /* conn->bits.close = FALSE; */

  return 0;
}
コード例 #24
0
ファイル: gssapi.c プロジェクト: wmene/yafc-1.1.2
static int
gss_auth(void *app_data, char *host)
{
    
    OM_uint32 maj_stat, min_stat;
    gss_name_t target_name;
    gss_buffer_desc input, output_token;
    int context_established = 0;
    char *p;
    int n;
    gss_channel_bindings_t bindings;
    struct gss_data *d = app_data;

    const char *knames[] = { "ftp", "host", NULL }, **kname = knames;
	    
    
    if(import_name(*kname++, host, &target_name))
	return AUTH_ERROR;

    input.length = 0;
    input.value = NULL;

    bindings = malloc(sizeof(*bindings));

    sockaddr_to_gss_address (myctladdr,
			     &bindings->initiator_addrtype,
			     &bindings->initiator_address);
    sockaddr_to_gss_address (hisctladdr,
			     &bindings->acceptor_addrtype,
			     &bindings->acceptor_address);

    bindings->application_data.length = 0;
    bindings->application_data.value = NULL;

    while(!context_established) {
       maj_stat = gss_init_sec_context(&min_stat,
					GSS_C_NO_CREDENTIAL,
					&d->context_hdl,
					target_name,
					GSS_C_NO_OID,
                                        GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG
                                          | GSS_C_DELEG_FLAG,
					0,
					bindings,
					&input,
					NULL,
					&output_token,
					NULL,
					NULL);
	if (GSS_ERROR(maj_stat)) {
	    OM_uint32 new_stat;
	    OM_uint32 msg_ctx = 0;
	    gss_buffer_desc status_string;

	    if(min_stat == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN && *kname != NULL) {
		if(import_name(*kname++, host, &target_name))
		    return AUTH_ERROR;
		continue;
	    }
	    
	    gss_display_status(&new_stat,
			       min_stat,
			       GSS_C_MECH_CODE,
			       GSS_C_NO_OID,
			       &msg_ctx,
			       &status_string);
	    printf("Error initializing security context: %s\n", 
		   (char*)status_string.value);
	    gss_release_buffer(&new_stat, &status_string);
	    return AUTH_CONTINUE;
	}

	gss_release_buffer(&min_stat, &input);
	if (output_token.length != 0) {
	    base64_encode(output_token.value, output_token.length, &p);
	    gss_release_buffer(&min_stat, &output_token);
	    n = ftp_cmd("ADAT %s", p);
	    free(p);
	}
	if (GSS_ERROR(maj_stat)) {
	    if (d->context_hdl != GSS_C_NO_CONTEXT)
		gss_delete_sec_context (&min_stat,
					&d->context_hdl,
					GSS_C_NO_BUFFER);
	    break;
	}
	if (maj_stat & GSS_S_CONTINUE_NEEDED) {
	    p = strstr(ftp->reply, "ADAT=");
	    if(p == NULL){
		printf("Error: expected ADAT in reply. got: %s\n",
		       ftp->reply);
		return AUTH_ERROR;
	    } else {
		p+=5;
		input.value = malloc(strlen(p));
		input.length = base64_decode(p, input.value);
	    }
	} else {
	    if(ftp->fullcode != 235) {
		printf("Unrecognized response code: %d\n", ftp->fullcode);
		return AUTH_ERROR;
	    }
	    context_established = 1;
	}
    }
    return AUTH_OK;
}
コード例 #25
0
ファイル: http_client.c プロジェクト: aosm/Heimdal
int
main(int argc, char **argv)
{
    int i, s, done, print_body, gssapi_done, gssapi_started, optidx = 0;
    const char *host, *page;
    struct http_req req;
    char *headers[99]; /* XXX */
    int num_headers;
    krb5_storage *sp;

    gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL;
    gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
    gss_name_t server = GSS_C_NO_NAME;
    gss_OID mech_oid, cred_mech_oid;
    OM_uint32 flags;
    OM_uint32 maj_stat, min_stat;

    setprogname(argv[0]);

    if(getarg(http_args, num_http_args, argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage (0);

    if(version_flag) {
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    mech_oid = select_mech(mech);

    if (cred_mech_str)
	cred_mech_oid = select_mech(cred_mech_str);
    else
	cred_mech_oid = mech_oid;

    if (argc != 1 && argc != 2)
	errx(1, "usage: %s host [page]", getprogname());
    host = argv[0];
    if (argc == 2)
	page = argv[1];
    else
	page = "/";

    flags = 0;
    if (delegate_flag)
	flags |= GSS_C_DELEG_FLAG;
    if (policy_flag)
	flags |= GSS_C_DELEG_POLICY_FLAG;
    if (mutual_flag)
	flags |= GSS_C_MUTUAL_FLAG;

    done = 0;
    num_headers = 0;
    gssapi_done = 0;
    gssapi_started = 0;

    if (client_str) {
	gss_buffer_desc name_buffer;
	gss_name_t name;
	gss_OID_set mechset = GSS_C_NO_OID_SET;

	name_buffer.value = client_str;
	name_buffer.length = strlen(client_str);

	maj_stat = gss_import_name(&min_stat, &name_buffer, GSS_C_NT_USER_NAME, &name);
	if (maj_stat)
	    errx(1, "failed to import name");

	if (cred_mech_oid) {
	    gss_create_empty_oid_set(&min_stat, &mechset);
	    gss_add_oid_set_member(&min_stat, cred_mech_oid, &mechset);
	}
	
	maj_stat = gss_acquire_cred(&min_stat, name, GSS_C_INDEFINITE,
				    mechset, GSS_C_INITIATE,
				    &client_cred, NULL, NULL);
	gss_release_name(&min_stat, &name);
	gss_release_oid_set(&min_stat, &mechset);
	if (maj_stat)
	    errx(1, "failed to find cred of name %s", client_str);
    }

    {
	gss_buffer_desc name_token;
	char *name;
	asprintf(&name, "%s@%s", gss_service, host);
	name_token.length = strlen(name);
	name_token.value = name;
	
	maj_stat = gss_import_name(&min_stat,
				   &name_token,
				   GSS_C_NT_HOSTBASED_SERVICE,
				   &server);
	if (GSS_ERROR(maj_stat))
	    gss_err (1, min_stat, "gss_inport_name: %s", name);
	free(name);
    }

    s = do_connect(host, port_str);
    if (s < 0)
	errx(1, "connection failed");

    sp = krb5_storage_from_fd(s);
    if (sp == NULL)
	errx(1, "krb5_storage_from_fd");

    do {
	print_body = 0;

	http_query(sp, host, page, headers, num_headers, &req);
	for (i = 0 ; i < num_headers; i++)
	    free(headers[i]);
	num_headers = 0;

	if (strstr(req.response, " 200 ") != NULL) {
	    print_body = 1;
	    done = 1;
	} else if (strstr(req.response, " 401 ") != NULL) {
	    if (http_find_header(&req, "WWW-Authenticate:") == NULL)
		errx(1, "Got %s but missed `WWW-Authenticate'", req.response);
	}

	if (!gssapi_done) {
	    const char *h = http_find_header(&req, "WWW-Authenticate:");
	    if (h == NULL)
		errx(1, "Got %s but missed `WWW-Authenticate'", req.response);

	    if (strncasecmp(h, "Negotiate", 9) == 0) {
		gss_buffer_desc input_token, output_token;

		if (verbose_flag)
		    printf("Negotiate found\n");

		i = 9;
		while(h[i] && isspace((unsigned char)h[i]))
		    i++;
		if (h[i] != '\0') {
		    size_t len = strlen(&h[i]);
		    int slen;
		    if (len == 0)
			errx(1, "invalid Negotiate token");
		    input_token.value = emalloc(len);
		    slen = base64_decode(&h[i], input_token.value);
		    if (slen < 0)
			errx(1, "invalid base64 Negotiate token %s", &h[i]);
		    input_token.length = slen;
		} else {
		    if (gssapi_started)
			errx(1, "Negotiate already started");
		    gssapi_started = 1;

		    input_token.length = 0;
		    input_token.value = NULL;
		}

		if (strstr(req.response, " 200 ") != NULL)
		    sleep(1);

		maj_stat =
		    gss_init_sec_context(&min_stat,
					 client_cred,
					 &context_hdl,
					 server,
					 mech_oid,
					 flags,
					 0,
					 GSS_C_NO_CHANNEL_BINDINGS,
					 &input_token,
					 NULL,
					 &output_token,
					 NULL,
					 NULL);
		if (maj_stat == GSS_S_CONTINUE_NEEDED) {

		} else if (maj_stat == GSS_S_COMPLETE) {
		    gss_name_t targ_name, src_name;
		    gss_buffer_desc name_buffer;
		    gss_OID mech_type;

		    gssapi_done = 1;

		    maj_stat = gss_inquire_context(&min_stat,
						   context_hdl,
						   &src_name,
						   &targ_name,
						   NULL,
						   &mech_type,
						   NULL,
						   NULL,
						   NULL);
		    if (GSS_ERROR(maj_stat))
			gss_err (1, min_stat, "gss_inquire_context");

		    printf("Negotiate done: %s\n", mech);

		    maj_stat = gss_display_name(&min_stat,
						src_name,
						&name_buffer,
						NULL);
		    if (GSS_ERROR(maj_stat))
			gss_print_errors(min_stat);
		    else
			printf("Source: %.*s\n",
			       (int)name_buffer.length,
			       (char *)name_buffer.value);

		    gss_release_buffer(&min_stat, &name_buffer);

		    maj_stat = gss_display_name(&min_stat,
						targ_name,
						&name_buffer,
						NULL);
		    if (GSS_ERROR(maj_stat))
			gss_print_errors(min_stat);
		    else
			printf("Target: %.*s\n",
			       (int)name_buffer.length,
			       (char *)name_buffer.value);

		    gss_release_name(&min_stat, &targ_name);
		    gss_release_buffer(&min_stat, &name_buffer);
		} else {
		    gss_err (1, min_stat, "gss_init_sec_context");
		}


		if (output_token.length) {
		    char *neg_token;

		    base64_encode(output_token.value,
				  (int)output_token.length,
				  &neg_token);

		    asprintf(&headers[0], "Authorization: Negotiate %s",
			     neg_token);

		    num_headers = 1;
		    free(neg_token);
		    gss_release_buffer(&min_stat, &output_token);
		}
		if (input_token.length)
		    free(input_token.value);

	    } else
		done = 1;
	} else
	    done = 1;

	if (print_body || verbose_flag)
	    printf("%.*s\n", (int)req.body_size, (char *)req.body);

	http_req_free(&req);
    } while (!done);

    if (gssapi_done == 0)
	errx(1, "gssapi not done but http dance done");

    krb5_storage_free(sp);
    close(s);

    return 0;
}
コード例 #26
0
ファイル: krb5-security.c プロジェクト: TonyChiang/amanda
/*

 * Negotiate a krb5 gss context from the client end.
 */
static int
gss_client(
    struct sec_handle *rh)
{
    struct sec_stream *rs = rh->rs;
    struct tcp_conn *rc = rs->rc;
    gss_buffer_desc send_tok, recv_tok, AA;
    gss_OID doid;
    OM_uint32 maj_stat, min_stat;
    unsigned int ret_flags;
    int rval = -1;
    int rvalue;
    gss_name_t gss_name;
    char *errmsg = NULL;

    auth_debug(1, "gss_client\n");

    send_tok.value = vstralloc("host/", rs->rc->hostname, NULL);
    send_tok.length = strlen(send_tok.value) + 1;
    maj_stat = gss_import_name(&min_stat, &send_tok, GSS_C_NULL_OID,
	&gss_name);
    if (maj_stat != (OM_uint32)GSS_S_COMPLETE) {
	security_seterror(&rh->sech, _("can't import name %s: %s"),
	    (char *)send_tok.value, gss_error(maj_stat, min_stat));
	amfree(send_tok.value);
	return (-1);
    }
    amfree(send_tok.value);
    rc->gss_context = GSS_C_NO_CONTEXT;
    maj_stat = gss_display_name(&min_stat, gss_name, &AA, &doid);
    dbprintf(_("gss_name %s\n"), (char *)AA.value);

    /*
     * Perform the context-establishement loop.
     *
     * Every generated token is stored in send_tok which is then
     * transmitted to the server; every received token is stored in
     * recv_tok (empty on the first pass) to be processed by
     * the next call to gss_init_sec_context.
     * 
     * GSS-API guarantees that send_tok's length will be non-zero
     * if and only if the server is expecting another token from us,
     * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if
     * and only if the server has another token to send us.
     */

    recv_tok.value = NULL;
    for (recv_tok.length = 0;;) {
	min_stat = 0;
	maj_stat = gss_init_sec_context(&min_stat,
	    GSS_C_NO_CREDENTIAL,
	    &rc->gss_context,
	    gss_name,
	    GSS_C_NULL_OID,
	    (OM_uint32)GSS_C_MUTUAL_FLAG|GSS_C_REPLAY_FLAG,
	    0, NULL,	/* no channel bindings */
	    (recv_tok.length == 0 ? GSS_C_NO_BUFFER : &recv_tok),
	    NULL,	/* ignore mech type */
	    &send_tok,
	    &ret_flags,
	    NULL);	/* ignore time_rec */

	if (recv_tok.length != 0) {
	    amfree(recv_tok.value);
	    recv_tok.length = 0;
	}
	if (maj_stat != (OM_uint32)GSS_S_COMPLETE && maj_stat != (OM_uint32)GSS_S_CONTINUE_NEEDED) {
	    security_seterror(&rh->sech,
		_("error getting gss context: %s %s"),
		gss_error(maj_stat, min_stat), (char *)send_tok.value);
	    goto done;
	}

	/*
	 * Send back the response
	 */
	if (send_tok.length != 0 && tcpm_send_token(rc, rc->write, rs->handle, &errmsg, send_tok.value, send_tok.length) < 0) {
	    security_seterror(&rh->sech, "%s", rc->errmsg);
	    gss_release_buffer(&min_stat, &send_tok);
	    goto done;
	}
	gss_release_buffer(&min_stat, &send_tok);

	/*
	 * If we need to continue, then register for more packets
	 */
	if (maj_stat != (OM_uint32)GSS_S_CONTINUE_NEEDED)
	    break;

        rvalue = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg,
				 (void *)&recv_tok.value,
				 (ssize_t *)&recv_tok.length, 60);
	if (rvalue <= 0) {
	    if (rvalue < 0)
		security_seterror(&rh->sech,
		    _("recv error in gss loop: %s"), rc->errmsg);
	    else
		security_seterror(&rh->sech, _("EOF in gss loop"));
	    goto done;
	}
    }

    rval = 0;
    rc->auth = 1;
done:
    gss_release_name(&min_stat, &gss_name);
    return (rval);
}
コード例 #27
0
ファイル: gssapi.c プロジェクト: antonywcl/AR-5315u_PLD
int
gssapi_get_itoken(struct ph1handle *iph1, int *lenp)
{
	struct gssapi_ph1_state *gps;
	gss_buffer_desc empty, name_token;
	gss_buffer_t itoken, rtoken, dummy;
	OM_uint32 maj_stat, min_stat;
	gss_name_t partner;

	if (gssapi_get_state(iph1) == NULL && gssapi_init(iph1) < 0)
		return -1;

	gps = gssapi_get_state(iph1);

	empty.length = 0;
	empty.value = NULL;
	dummy = &empty;

	if (iph1->approval != NULL && iph1->approval->gssid != NULL) {
		plog(LLV_DEBUG, LOCATION, NULL,
		    "using provided service '%.*s'\n",
		    iph1->approval->gssid->l, iph1->approval->gssid->v);
		name_token.length = iph1->approval->gssid->l;
		name_token.value = iph1->approval->gssid->v;
		maj_stat = gss_import_name(&min_stat, &name_token,
		    GSS_C_NO_OID, &partner);
		if (GSS_ERROR(maj_stat)) {
			gssapi_error(min_stat, LOCATION, "import of %.*s\n",
			    name_token.length, name_token.value);
			return -1;
		}
	} else
		if (gssapi_get_default_name(iph1, 1, &partner) < 0)
			return -1;

	rtoken = gps->gsscnt_p == 0 ? dummy : &gps->gss_p[gps->gsscnt_p - 1];
	itoken = &gps->gss[gps->gsscnt];

	gps->gss_status = gss_init_sec_context(&min_stat, gps->gss_cred,
	    &gps->gss_context, partner, GSS_C_NO_OID,
	    GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG |
		GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG,
	    0, GSS_C_NO_CHANNEL_BINDINGS, rtoken, NULL,
	    itoken, NULL, NULL);

	if (GSS_ERROR(gps->gss_status)) {
		gssapi_error(min_stat, LOCATION, "init_sec_context\n");
		maj_stat = gss_release_name(&min_stat, &partner);
		if (GSS_ERROR(maj_stat))
			gssapi_error(min_stat, LOCATION, "release name\n");
		return -1;
	}
	maj_stat = gss_release_name(&min_stat, &partner);
	if (GSS_ERROR(maj_stat))
		gssapi_error(min_stat, LOCATION, "release name\n");

	plog(LLV_DEBUG, LOCATION, NULL, "gss_init_sec_context status %x\n",
	    gps->gss_status);

	if (lenp)
		*lenp = itoken->length;

	if (itoken->length != 0)
		gps->gsscnt++;

	return 0;
}
int main()
{
    OM_uint32                           init_maj_stat;
    OM_uint32                           accept_maj_stat;
    OM_uint32                           maj_stat;
    OM_uint32                           min_stat;
    OM_uint32                           ret_flags;
    OM_uint32                           req_flags = 0;
    OM_uint32                           time_rec;
    gss_buffer_desc                     send_tok;
    gss_buffer_desc                     recv_tok;
    gss_buffer_desc *                   token_ptr;
    gss_OID                             mech_type;
    gss_name_t                          target_name;
    gss_ctx_id_t                        init_context;
    gss_ctx_id_t                        accept_context;
    gss_ctx_id_t                        del_init_context;
    gss_ctx_id_t                        del_accept_context;
    gss_cred_id_t                       delegated_cred;
    gss_cred_id_t                       imported_cred;
    gss_cred_id_t                       cred_handle;
    char *                              error_str;
    globus_result_t                     result;
    globus_gsi_cert_utils_cert_type_t   cert_type;
    int                                 rc = EXIT_SUCCESS;

    printf("1..1\n");
    /* Activate Modules */
    globus_module_activate(GLOBUS_GSI_GSSAPI_MODULE);

    /* Initialize variables */
    
    token_ptr = GSS_C_NO_BUFFER;
    init_context = GSS_C_NO_CONTEXT;
    accept_context = GSS_C_NO_CONTEXT;
    del_init_context = GSS_C_NO_CONTEXT;
    del_accept_context = GSS_C_NO_CONTEXT;
    delegated_cred = GSS_C_NO_CREDENTIAL;
    accept_maj_stat = GSS_S_CONTINUE_NEEDED;
    ret_flags = 0;
    req_flags |= GSS_C_GLOBUS_LIMITED_DELEG_PROXY_FLAG;


    /* acquire the credential */

    maj_stat = gss_acquire_cred(&min_stat,
                                NULL,
                                GSS_C_INDEFINITE,
                                GSS_C_NO_OID_SET,
                                GSS_C_BOTH,
                                &cred_handle,
                                NULL,
                                NULL);

    if(maj_stat != GSS_S_COMPLETE)
    {
        globus_gsi_gssapi_test_print_error(stderr, maj_stat, min_stat);
        rc = EXIT_FAILURE;
        goto fail;
    }

    
    /* get the subject name */
    
    maj_stat = gss_inquire_cred(&min_stat, 
                                cred_handle,
                                &target_name,
                                NULL,
                                NULL,
                                NULL);

    if(maj_stat != GSS_S_COMPLETE)
    {
        globus_gsi_gssapi_test_print_error(stderr, maj_stat, min_stat);
        rc = EXIT_FAILURE;
        goto fail;
    }


    /* set up the first security context */
    
    init_maj_stat = gss_init_sec_context(&min_stat,
                                         cred_handle,
                                         &init_context,
                                         target_name,
                                         GSS_C_NULL_OID,
                                         0,
                                         0,
                                         GSS_C_NO_CHANNEL_BINDINGS,
                                         token_ptr,
                                         NULL,
                                         &send_tok,
                                         NULL,
                                         NULL);


    if(init_maj_stat != GSS_S_CONTINUE_NEEDED)
    {
        globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat);
        rc = EXIT_FAILURE;
        goto fail;
    }

    while(1)
    {
        
        accept_maj_stat=gss_accept_sec_context(&min_stat,
                                               &accept_context,
                                               GSS_C_NO_CREDENTIAL,
                                               &send_tok, 
                                               GSS_C_NO_CHANNEL_BINDINGS,
                                               NULL,
                                               &mech_type,
                                               &recv_tok,
                                               &ret_flags,
                                               /* ignore time_rec */
                                               NULL, 
                                               NULL);

        if(accept_maj_stat != GSS_S_COMPLETE &&
           accept_maj_stat != GSS_S_CONTINUE_NEEDED)
        {
            globus_gsi_gssapi_test_print_error(stderr, accept_maj_stat, min_stat);
            rc = EXIT_FAILURE;
            goto fail;
        }
        else if(accept_maj_stat == GSS_S_COMPLETE)
        {
            break;
        }

        init_maj_stat = gss_init_sec_context(&min_stat,
                                             GSS_C_NO_CREDENTIAL,
                                             &init_context,
                                             target_name,
                                             GSS_C_NULL_OID,
                                             0,
                                             0,
                                             GSS_C_NO_CHANNEL_BINDINGS,
                                             &recv_tok,
                                             NULL,
                                             &send_tok,
                                             NULL,
                                             NULL);
        
        
        if(init_maj_stat != GSS_S_COMPLETE &&
           init_maj_stat != GSS_S_CONTINUE_NEEDED)
        {
            globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat);
            rc = EXIT_FAILURE;
            goto fail;
        }
    }

    printf("# %s:%d: Successfully established initial security context\n",
           __FILE__,
           __LINE__);


    /* delegate our credential over the initial security context and
     * insert a restriction extension into the delegated credential.
     * This is a post GT 2.0 feature.
     */


    init_maj_stat = gss_init_delegation(&min_stat,
                                        init_context,
                                        cred_handle,
                                        GSS_C_NO_OID,
                                        GSS_C_NO_OID_SET,
                                        GSS_C_NO_BUFFER_SET,
                                        token_ptr,
                                        req_flags,
                                        0,
                                        &send_tok);
    

    if(init_maj_stat != GSS_S_COMPLETE &&
       init_maj_stat != GSS_S_CONTINUE_NEEDED)
    {
        globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat);
        rc = EXIT_FAILURE;
        goto fail;
    }

    while(1)
    {
        accept_maj_stat=gss_accept_delegation(&min_stat,
                                              accept_context,
                                              GSS_C_NO_OID_SET,
                                              GSS_C_NO_BUFFER_SET,
                                              &send_tok,
                                              req_flags,
                                              0,
                                              &time_rec,
                                              &delegated_cred,
                                              &mech_type,
                                              &recv_tok);
        
        if(accept_maj_stat != GSS_S_COMPLETE &&
           accept_maj_stat != GSS_S_CONTINUE_NEEDED)
        {
            globus_gsi_gssapi_test_print_error(stderr, accept_maj_stat, min_stat);
            rc = EXIT_FAILURE;
            goto fail;
        }
        else if(accept_maj_stat == GSS_S_COMPLETE)
        {
            break;
        }

        init_maj_stat = gss_init_delegation(&min_stat,
                                            init_context,
                                            cred_handle,
                                            GSS_C_NO_OID,
                                            GSS_C_NO_OID_SET,
                                            GSS_C_NO_BUFFER_SET,
                                            &recv_tok,
                                            req_flags,
                                            0,
                                            &send_tok);


        if(init_maj_stat != GSS_S_COMPLETE &&
           init_maj_stat != GSS_S_CONTINUE_NEEDED)
        {
            globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat);
            rc = EXIT_FAILURE;
            goto fail;
        }
    }
    
    printf("# %s:%d: Successfully delegated credential\n",
           __FILE__,
           __LINE__);

    /* export and import the delegated credential */
    /* this can be done both to a buffer and to a file */
    /* New in GT 2.0 */

    maj_stat = gss_export_cred(&min_stat,
                               delegated_cred,
                               GSS_C_NO_OID,
                               0,
                               &send_tok);

    if(maj_stat != GSS_S_COMPLETE)
    {
        globus_gsi_gssapi_test_print_error(stderr, maj_stat, min_stat);
        rc = EXIT_FAILURE;
        goto fail;
    }

    
    maj_stat = gss_import_cred(&min_stat,
                               &imported_cred,
                               GSS_C_NO_OID,
                               0,
                               &send_tok,
                               0,
                               &time_rec);


    if(maj_stat != GSS_S_COMPLETE)
    {
        globus_gsi_gssapi_test_print_error(stderr, maj_stat, min_stat);
        rc = EXIT_FAILURE;
        goto fail;
    }

    printf("# %s:%d: Successfully exported/imported the delegated credential\n",
           __FILE__,
           __LINE__);

    /* set up another security context using the delegated credential */
    
    init_maj_stat = gss_init_sec_context(&min_stat,
                                         imported_cred,
                                         &del_init_context,
                                         target_name,
                                         GSS_C_NULL_OID,
                                         0,
                                         0,
                                         GSS_C_NO_CHANNEL_BINDINGS,
                                         token_ptr,
                                         NULL,
                                         &send_tok,
                                         NULL,
                                         NULL);


    if(init_maj_stat != GSS_S_COMPLETE &&
       init_maj_stat != GSS_S_CONTINUE_NEEDED)
    {
        globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat);
        rc = EXIT_FAILURE;
        goto fail;
    }


    
    while(1)
    {
        accept_maj_stat=gss_accept_sec_context(&min_stat,
                                               &del_accept_context,
                                               imported_cred,
                                               &send_tok, 
                                               GSS_C_NO_CHANNEL_BINDINGS,
                                               NULL,
                                               &mech_type,
                                               &recv_tok,
                                               &ret_flags,
                                               /* ignore time_rec */
                                               NULL, 
                                               NULL);

        if(accept_maj_stat != GSS_S_COMPLETE &&
           accept_maj_stat != GSS_S_CONTINUE_NEEDED)
        {
            globus_gsi_gssapi_test_print_error(stderr, accept_maj_stat, min_stat);
            rc = EXIT_FAILURE;
            goto fail;
        }
        else if(accept_maj_stat == GSS_S_COMPLETE)
        {
            break;
        }
        
        init_maj_stat = gss_init_sec_context(&min_stat,
                                             imported_cred,
                                             &del_init_context,
                                             target_name,
                                             GSS_C_NULL_OID,
                                             0,
                                             0,
                                             GSS_C_NO_CHANNEL_BINDINGS,
                                             &recv_tok,
                                             NULL,
                                             &send_tok,
                                             NULL,
                                             NULL);
        
        
        if(init_maj_stat != GSS_S_COMPLETE &&
           init_maj_stat != GSS_S_CONTINUE_NEEDED)
        {
            globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat);
            rc = EXIT_FAILURE;
            goto fail;
        }
    }

    /* got sec context based on delegated cred now */
    printf("# %s:%d: Successfully established security context with delegated credential\n",
           __FILE__,
           __LINE__);

    /* Verify that the delegated credential is a limited proxy */
    result = globus_gsi_cred_get_cert_type(
        ((gss_cred_id_desc *)imported_cred)->cred_handle,
        &cert_type);
    if(result != GLOBUS_SUCCESS)
    {
        char *                          error_str;
        globus_object_t *               error_obj;

        error_obj = globus_error_get(result);
        error_str = globus_error_print_chain(error_obj);
        fprintf(stderr, "%s", error_str);
        globus_libc_free(error_str);
        globus_object_free(error_obj);
        rc = EXIT_FAILURE;
        goto fail;
    }

    if (! GLOBUS_GSI_CERT_UTILS_IS_LIMITED_PROXY(cert_type))
    {
        fprintf(stderr,
                "Invalid certificate type. Expected a limited proxy, got %d\n",
                (int) cert_type);
        rc = EXIT_FAILURE;
        goto fail;
    }

fail:
    printf("%s gssapi_limited_delegation_test\n",
            (rc==EXIT_SUCCESS) ? "ok" : "not ok");
    globus_module_deactivate_all();
    
    exit(rc);    
}
コード例 #29
0
ファイル: gssapictx.c プロジェクト: coapp-packages/bind
isc_result_t
dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
		   isc_buffer_t *outtoken, gss_ctx_id_t *gssctx,
		   isc_mem_t *mctx, char **err_message)
{
#ifdef GSSAPI
	isc_region_t r;
	isc_buffer_t namebuf;
	gss_name_t gname;
	OM_uint32 gret, minor, ret_flags, flags;
	gss_buffer_desc gintoken, *gintokenp, gouttoken = GSS_C_EMPTY_BUFFER;
	isc_result_t result;
	gss_buffer_desc gnamebuf;
	unsigned char array[DNS_NAME_MAXTEXT + 1];

	/* Client must pass us a valid gss_ctx_id_t here */
	REQUIRE(gssctx != NULL);
	REQUIRE(mctx != NULL);

	isc_buffer_init(&namebuf, array, sizeof(array));
	name_to_gbuffer(name, &namebuf, &gnamebuf);

	/* Get the name as a GSS name */
	gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
	if (gret != GSS_S_COMPLETE) {
		gss_err_message(mctx, gret, minor, err_message);
		result = ISC_R_FAILURE;
		goto out;
	}

	if (intoken != NULL) {
		/* Don't call gss_release_buffer for gintoken! */
		REGION_TO_GBUFFER(*intoken, gintoken);
		gintokenp = &gintoken;
	} else {
		gintokenp = NULL;
	}

	/*
	 * Note that we don't set GSS_C_SEQUENCE_FLAG as Windows DNS
	 * servers don't like it.
	 */
	flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG;

	gret = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, gssctx,
				    gname, GSS_SPNEGO_MECHANISM, flags,
				    0, NULL, gintokenp,
				    NULL, &gouttoken, &ret_flags, NULL);

	if (gret != GSS_S_COMPLETE && gret != GSS_S_CONTINUE_NEEDED) {
		gss_err_message(mctx, gret, minor, err_message);
		gss_log(3, "Failure initiating security context: %s",
			*err_message);
		result = ISC_R_FAILURE;
		goto out;
	}

	/*
	 * XXXSRA Not handled yet: RFC 3645 3.1.1: check ret_flags
	 * MUTUAL and INTEG flags, fail if either not set.
	 */

	/*
	 * RFC 2744 states the a valid output token has a non-zero length.
	 */
	if (gouttoken.length != 0) {
		GBUFFER_TO_REGION(gouttoken, r);
		RETERR(isc_buffer_copyregion(outtoken, &r));
		(void)gss_release_buffer(&minor, &gouttoken);
	}
	(void)gss_release_name(&minor, &gname);

	if (gret == GSS_S_COMPLETE)
		result = ISC_R_SUCCESS;
	else
		result = DNS_R_CONTINUE;

 out:
	return (result);
#else
	UNUSED(name);
	UNUSED(intoken);
	UNUSED(outtoken);
	UNUSED(gssctx);
	UNUSED(mctx);
	UNUSED(err_message);

	return (ISC_R_NOTIMPLEMENTED);
#endif
}
コード例 #30
0
ファイル: auth.c プロジェクト: jianglei12138/cups
int					/* O - 0 on success, -1 on error */
_cupsSetNegotiateAuthString(
    http_t     *http,			/* I - Connection to server */
    const char *method,			/* I - Request method ("GET", "POST", "PUT") */
    const char *resource)		/* I - Resource path */
{
  OM_uint32	minor_status,		/* Minor status code */
		major_status;		/* Major status code */
  gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
					/* Output token */


  (void)method;
  (void)resource;

#  ifdef __APPLE__
 /*
  * If the weak-linked GSSAPI/Kerberos library is not present, don't try
  * to use it...
  */

  if (&gss_init_sec_context == NULL)
  {
    DEBUG_puts("1_cupsSetNegotiateAuthString: Weak-linked GSSAPI/Kerberos "
               "framework is not present");
    return (-1);
  }
#  endif /* __APPLE__ */

  if (http->gssname == GSS_C_NO_NAME)
  {
    http->gssname = cups_gss_getname(http, _cupsGSSServiceName());
  }

  if (http->gssctx != GSS_C_NO_CONTEXT)
  {
    gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
    http->gssctx = GSS_C_NO_CONTEXT;
  }

  major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL,
				      &http->gssctx,
				      http->gssname, http->gssmech,
				      GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG,
				      GSS_C_INDEFINITE,
				      GSS_C_NO_CHANNEL_BINDINGS,
				      GSS_C_NO_BUFFER, &http->gssmech,
				      &output_token, NULL, NULL);

#ifdef HAVE_GSS_ACQUIRE_CRED_EX_F
  if (major_status == GSS_S_NO_CRED)
  {
   /*
    * Ask the user for credentials...
    */

    char		prompt[1024],	/* Prompt for user */
			userbuf[256];	/* Kerberos username */
    const char		*username,	/* Username string */
			*password;	/* Password string */
    _cups_gss_acquire_t	data;		/* Callback data */
    gss_auth_identity_desc identity;	/* Kerberos user identity */
    _cups_globals_t	*cg = _cupsGlobals();
					/* Per-thread global data */

    if (!cg->lang_default)
      cg->lang_default = cupsLangDefault();

    snprintf(prompt, sizeof(prompt),
             _cupsLangString(cg->lang_default, _("Password for %s on %s? ")),
	     cupsUser(), http->gsshost);

    if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL)
      return (-1);

   /*
    * Try to acquire credentials...
    */

    username = cupsUser();
    if (!strchr(username, '@'))
    {
      snprintf(userbuf, sizeof(userbuf), "%s@%s", username, http->gsshost);
      username = userbuf;
    }

    identity.type           = GSS_AUTH_IDENTITY_TYPE_1;
    identity.flags          = 0;
    identity.username       = (char *)username;
    identity.realm          = (char *)"";
    identity.password       = (char *)password;
    identity.credentialsRef = NULL;

    data.sem   = dispatch_semaphore_create(0);
    data.major = 0;
    data.creds = NULL;

    if (data.sem)
    {
      major_status = gss_acquire_cred_ex_f(NULL, GSS_C_NO_NAME, 0,
				           GSS_C_INDEFINITE, GSS_KRB5_MECHANISM,
					   GSS_C_INITIATE, &identity, &data,
					   cups_gss_acquire);

      if (major_status == GSS_S_COMPLETE)
      {
	dispatch_semaphore_wait(data.sem, DISPATCH_TIME_FOREVER);
	major_status = data.major;
      }

      dispatch_release(data.sem);

      if (major_status == GSS_S_COMPLETE)
      {
        OM_uint32	release_minor;	/* Minor status from releasing creds */

	major_status = gss_init_sec_context(&minor_status, data.creds,
					    &http->gssctx,
					    http->gssname, http->gssmech,
					    GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG,
					    GSS_C_INDEFINITE,
					    GSS_C_NO_CHANNEL_BINDINGS,
					    GSS_C_NO_BUFFER, &http->gssmech,
					    &output_token, NULL, NULL);
        gss_release_cred(&release_minor, &data.creds);
      }
    }
  }
#endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */

  if (GSS_ERROR(major_status))
  {
    cups_gss_printf(major_status, minor_status,
		    "_cupsSetNegotiateAuthString: Unable to initialize "
		    "security context");
    return (-1);
  }

#ifdef DEBUG
  else if (major_status == GSS_S_CONTINUE_NEEDED)
    cups_gss_printf(major_status, minor_status,
		    "_cupsSetNegotiateAuthString: Continuation needed!");
#endif /* DEBUG */

  if (output_token.length > 0 && output_token.length <= 65536)
  {
   /*
    * Allocate the authorization string since Windows KDCs can have
    * arbitrarily large credentials...
    */

    int authsize = 10 +			/* "Negotiate " */
		   (int)output_token.length * 4 / 3 + 1 + 1;
		   			/* Base64 + nul */

    httpSetAuthString(http, NULL, NULL);

    if ((http->authstring = malloc((size_t)authsize)) == NULL)
    {
      http->authstring = http->_authstring;
      authsize         = sizeof(http->_authstring);
    }

    strlcpy(http->authstring, "Negotiate ", (size_t)authsize);
    httpEncode64_2(http->authstring + 10, authsize - 10, output_token.value,
		   (int)output_token.length);

    gss_release_buffer(&minor_status, &output_token);
  }
  else
  {
    DEBUG_printf(("1_cupsSetNegotiateAuthString: Kerberos credentials too "
                  "large - %d bytes!", (int)output_token.length));
    gss_release_buffer(&minor_status, &output_token);

    return (-1);
  }

  return (0);
}