示例#1
0
文件: httpd.c 项目: forest1040/kozos
int httpd_main(int argc, char *argv[])
{
  char *p = NULL, *r;
  char *buffer;
  int number = 0, ret;
  struct netbuf *buf;

  send_accept();

  buffer = kz_kmalloc(DEFAULT_NETBUF_SIZE);

  while (1) {
    kz_recv(MSGBOX_ID_HTTPD, NULL, (void *)&buf);

    switch (buf->cmd) {
    case TCP_CMD_ESTAB:
      number = buf->option.tcp.establish.number;
      p = buffer;
      break;

    case TCP_CMD_CLOSE:
      number = 0;
      send_accept();
      break;

    case TCP_CMD_RECV:
      memcpy(p, buf->top, buf->size);
      p += buf->size;
      *p = '\0';

      r = strchr(buffer, '\n');
      if (r) {
	*r = '\0';
	r++;
	ret = parse(number, buffer);
	memmove(buffer, r, p - r + 1);
	p -= (r - buffer);
	if (ret) send_close(number);
      }
      break;
    }

    kz_kmfree(buf);
  }

  return 0;
}
示例#2
0
	void i2p_stream::read_line(error_code const& e, boost::shared_ptr<handler_type> h)
	{
		TORRENT_ASSERT(m_magic == 0x1337);
#if defined TORRENT_ASIO_DEBUGGING
		complete_async("i2p_stream::read_line");
#endif
		if (handle_error(e, h)) return;

		int read_pos = m_buffer.size();

		// look for \n which means end of the response
		if (m_buffer[read_pos - 1] != '\n')
		{
#if defined TORRENT_ASIO_DEBUGGING
			add_outstanding_async("i2p_stream::read_line");
#endif
			// read another byte from the socket
			m_buffer.resize(read_pos + 1);
			async_read(m_sock, boost::asio::buffer(&m_buffer[read_pos], 1)
				, boost::bind(&i2p_stream::read_line, this, _1, h));
			return;
		}
		m_buffer[read_pos - 1] = 0;

		if (m_command == cmd_incoming)
		{
			// this is the line containing the destination
			// of the incoming connection in an accept call
			m_dest = &m_buffer[0];
			(*h)(e);
			std::vector<char>().swap(m_buffer);
			return;
		}

		error_code invalid_response(i2p_error::parse_failed
			, get_i2p_category());

		// null-terminate the string and parse it
		m_buffer.push_back(0);
		char* ptr = &m_buffer[0];
		char* next = ptr;

		char const* expect1 = 0;
		char const* expect2 = 0;

		switch (m_state)
		{
			case read_hello_response:
				expect1 = "HELLO";
				expect2 = "REPLY";
				break;
			case read_connect_response:
			case read_accept_response:
				expect1 = "STREAM";
				expect2 = "STATUS";
				break;
			case read_session_create_response:
				expect1 = "SESSION";
				expect2 = "STATUS";
				break;
			case read_name_lookup_response:
				expect1 = "NAMING";
				expect2 = "REPLY";
				break;
		}

//		fprintf(stderr, "<<< %s\n", &m_buffer[0]);
		ptr = string_tokenize(next, ' ', &next);
		if (ptr == 0 || expect1 == 0 || strcmp(expect1, ptr)) { handle_error(invalid_response, h); return; }
		ptr = string_tokenize(next, ' ', &next);
		if (ptr == 0 || expect2 == 0 || strcmp(expect2, ptr)) { handle_error(invalid_response, h); return; }

		int result = 0;
//		char const* message = 0;
//		float version = 3.0f;

		for(;;)
		{
			char* name = string_tokenize(next, '=', &next);
			if (name == 0) break;
//			fprintf(stderr, "name=\"%s\"\n", name);
			char* ptr2 = string_tokenize(next, ' ', &next);
			if (ptr2 == 0) { handle_error(invalid_response, h); return; }
//			fprintf(stderr, "value=\"%s\"\n", ptr2);

			if (strcmp("RESULT", name) == 0)
			{
				if (strcmp("OK", ptr2) == 0)
					result = i2p_error::no_error;
				else if (strcmp("CANT_REACH_PEER", ptr2) == 0)
					result = i2p_error::cant_reach_peer;
				else if (strcmp("I2P_ERROR", ptr2) == 0)
					result = i2p_error::i2p_error;
				else if (strcmp("INVALID_KEY", ptr2) == 0)
					result = i2p_error::invalid_key;
				else if (strcmp("INVALID_ID", ptr2) == 0)
					result = i2p_error::invalid_id;
				else if (strcmp("TIMEOUT", ptr2) == 0)
					result = i2p_error::timeout;
				else if (strcmp("KEY_NOT_FOUND", ptr2) == 0)
					result = i2p_error::key_not_found;
				else if (strcmp("DUPLICATED_ID", ptr2) == 0)
					result = i2p_error::duplicated_id;
				else
					result = i2p_error::num_errors; // unknown error
			}
			else if (strcmp("MESSAGE", name) == 0)
			{
//				message = ptr2;
			}
			else if (strcmp("VERSION", name) == 0)
			{
//				version = float(atof(ptr2));
			}
			else if (strcmp("VALUE", name) == 0)
			{
				m_name_lookup = ptr2;
			}
			else if (strcmp("DESTINATION", name) == 0)
			{
				m_dest = ptr2;
			}
		}

		error_code ec(result, get_i2p_category());
		switch (result)
		{
			case i2p_error::no_error:
			case i2p_error::invalid_key:
				break;
			default:
			{
				handle_error (ec, h);
				return;
			}
		}

		switch (m_state)
		{
		case read_hello_response:
			switch (m_command)
			{
				case cmd_create_session:
					send_session_create(h);
					break;
				case cmd_accept:
					send_accept(h);
					break;
				case cmd_connect:
					send_connect(h);
					break;
				default:
					(*h)(e);
					std::vector<char>().swap(m_buffer);
			}
			break;
		case read_connect_response:
		case read_session_create_response:
		case read_name_lookup_response:
			(*h)(ec);
			std::vector<char>().swap(m_buffer);
			break;
		case read_accept_response:
			// the SAM bridge is waiting for an incoming
			// connection.
			// wait for one more line containing
			// the destination of the remote peer
			m_command = cmd_incoming;
			m_buffer.resize(1);
#if defined TORRENT_ASIO_DEBUGGING
			add_outstanding_async("i2p_stream::read_line");
#endif
			async_read(m_sock, boost::asio::buffer(m_buffer)
				, boost::bind(&i2p_stream::read_line, this, _1, h));
			break;
		}

		return;
	}
示例#3
0
OM_uint32 KRB5_LIB_FUNCTION gss_accept_sec_context_spnego
           (OM_uint32 * minor_status,
            gss_ctx_id_t * context_handle,
            const gss_cred_id_t acceptor_cred_handle,
            const gss_buffer_t input_token_buffer,
            const gss_channel_bindings_t input_chan_bindings,
            gss_name_t * src_name,
            gss_OID * mech_type,
            gss_buffer_t output_token,
            OM_uint32 * ret_flags,
            OM_uint32 * time_rec,
            gss_cred_id_t * delegated_cred_handle)
{
   NegTokenInit init_token;
   OM_uint32 major_status;
   OM_uint32 minor_status2;
   gss_buffer_desc ibuf, obuf;
   gss_buffer_t ot = NULL;
   unsigned char *buf;
   size_t buf_size;
   size_t len, taglen, ni_len;
   int found = 0;
   int ret, i;

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

   ret = gssapi_spnego_decapsulate(minor_status, input_token_buffer,
	 			   &buf, &buf_size, GSS_SPNEGO_MECH);
   if (ret)
      return ret;

   ret = der_match_tag_and_length(buf, buf_size, KERB_CTXT, CONS,
	 			  0, &len, &taglen);
   if (ret)
      return ret;

   ret = decode_NegTokenInit(buf + taglen, len, &init_token, &ni_len);
   if (ret) {
      *minor_status = EINVAL; /* XXX */
      return GSS_S_DEFECTIVE_TOKEN;
   }

   if (init_token.mechTypes == NULL)
      return send_reject (minor_status, output_token);

   for (i = 0; !found && i < init_token.mechTypes->len; ++i) {
      unsigned char mechbuf[17];
      size_t mech_len;

      ret = der_put_oid (mechbuf + sizeof(mechbuf) - 1,
                         sizeof(mechbuf),
                         &init_token.mechTypes->val[i],
                         &mech_len);
      if (ret)
          return GSS_S_DEFECTIVE_TOKEN;
      if (mech_len == GSS_KRB5_MECH->length
          && memcmp(GSS_KRB5_MECH->elements,
                    mechbuf + sizeof(mechbuf) - mech_len,
                    mech_len) == 0)
          found = 1;
   }

   if (!found)
      return send_reject (minor_status, output_token);

   if (init_token.mechToken != NULL) {
      ibuf.length = init_token.mechToken->length;
      ibuf.value  = init_token.mechToken->data;

      major_status = gss_accept_sec_context(minor_status,
	    				    context_handle,
					    acceptor_cred_handle,
					    &ibuf,
					    input_chan_bindings,
					    src_name,
					    mech_type,
					    &obuf,
					    ret_flags,
					    time_rec,
					    delegated_cred_handle);
      if (GSS_ERROR(major_status)) {
	 send_reject (&minor_status2, output_token);
	 return major_status;
      }
      ot = &obuf;
   }

   ret = send_accept (&minor_status2, output_token, ot);
   if (ot != NULL)
      gss_release_buffer(&minor_status2, ot);

   return ret;
}
示例#4
0
static OM_uint32 GSSAPI_CALLCONV
acceptor_continue
	   (OM_uint32 * minor_status,
	    gss_ctx_id_t * context_handle,
	    const gss_cred_id_t acceptor_cred_handle,
	    const gss_buffer_t input_token_buffer,
	    const gss_channel_bindings_t input_chan_bindings,
	    gss_name_t * src_name,
	    gss_OID * mech_type,
	    gss_buffer_t output_token,
	    OM_uint32 * ret_flags,
	    OM_uint32 * time_rec,
	    gss_cred_id_t *delegated_cred_handle
	   )
{
    OM_uint32 ret, ret2, minor;
    NegotiationToken nt;
    size_t nt_len;
    NegTokenResp *na;
    unsigned int negResult = accept_incomplete;
    gss_buffer_t mech_input_token = GSS_C_NO_BUFFER;
    gss_buffer_t mech_output_token = GSS_C_NO_BUFFER;
    gss_buffer_desc mech_buf;
    gssspnego_ctx ctx;

    mech_buf.value = NULL;

    ctx = (gssspnego_ctx)*context_handle;

    /*
     * The GSS-API encapsulation is only present on the initial
     * context token (negTokenInit).
     */

    ret = decode_NegotiationToken(input_token_buffer->value,
				  input_token_buffer->length,
				  &nt, &nt_len);
    if (ret) {
	*minor_status = ret;
	return GSS_S_DEFECTIVE_TOKEN;
    }
    if (nt.element != choice_NegotiationToken_negTokenResp) {
	*minor_status = 0;
	return GSS_S_DEFECTIVE_TOKEN;
    }
    na = &nt.u.negTokenResp;

    if (na->negResult != NULL) {
	negResult = *(na->negResult);
    }

    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);

    {
	gss_buffer_desc ibuf, obuf;
	int require_mic, get_mic = 0;
	int require_response;
	heim_octet_string *mic;

	if (na->responseToken != NULL) {
	    ibuf.length = na->responseToken->length;
	    ibuf.value = na->responseToken->data;
	    mech_input_token = &ibuf;
	} else {
	    ibuf.value = NULL;
	    ibuf.length = 0;
	}

	if (mech_input_token != GSS_C_NO_BUFFER) {

	    if (ctx->mech_src_name != GSS_C_NO_NAME)
		gss_release_name(&minor, &ctx->mech_src_name);

	    ret = gss_accept_sec_context(&minor,
					 &ctx->negotiated_ctx_id,
					 acceptor_cred_handle,
					 mech_input_token,
					 input_chan_bindings,
					 &ctx->mech_src_name,
					 &ctx->negotiated_mech_type,
					 &obuf,
					 &ctx->mech_flags,
					 &ctx->mech_time_rec,
					 delegated_cred_handle);

	    if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) {
		mech_output_token = &obuf;
	    }
	    if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
		free_NegotiationToken(&nt);
		gss_mg_collect_error(ctx->negotiated_mech_type, ret, minor);
		send_reject (minor_status, output_token);
		HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
		return ret;
	    }
	    if (ret == GSS_S_COMPLETE)
		ctx->open = 1;
	} else
	    ret = GSS_S_COMPLETE;

	ret2 = _gss_spnego_require_mechlist_mic(minor_status,
						ctx,
						&require_mic);
	if (ret2)
	    goto out;

	ctx->require_mic = require_mic;

	mic = na->mechListMIC;
	if (mic != NULL)
	    require_mic = 1;

	if (ret == GSS_S_COMPLETE)
	    ret = acceptor_complete(minor_status,
				    ctx,
				    &get_mic,
				    &mech_buf,
				    mech_input_token,
				    mech_output_token,
				    na->mechListMIC,
				    output_token);

	if (ctx->mech_flags & GSS_C_DCE_STYLE)
	    require_response = (negResult != accept_completed);
	else
	    require_response = 0;

	/*
	 * Check whether we need to send a result: there should be only
	 * one accept_completed response sent in the entire negotiation
	 */
	if ((mech_output_token != GSS_C_NO_BUFFER &&
	     mech_output_token->length != 0)
	    || (ctx->open && negResult == accept_incomplete)
	    || require_response
	    || get_mic) {
	    ret2 = send_accept (minor_status,
				ctx,
				mech_output_token,
				0,
				get_mic ? &mech_buf : NULL,
				output_token);
	    if (ret2)
		goto out;
	}

     out:
	if (ret2 != GSS_S_COMPLETE)
	    ret = ret2;
	if (mech_output_token != NULL)
	    gss_release_buffer(&minor, mech_output_token);
	if (mech_buf.value != NULL)
	    free(mech_buf.value);
	free_NegotiationToken(&nt);
    }

    if (ret == GSS_S_COMPLETE) {
	if (src_name != NULL && ctx->mech_src_name != NULL) {
	    spnego_name name;

	    name = calloc(1, sizeof(*name));
	    if (name) {
		name->mech = ctx->mech_src_name;
		ctx->mech_src_name = NULL;
		*src_name = (gss_name_t)name;
	    }
	}
    }

    if (mech_type != NULL)
	*mech_type = ctx->negotiated_mech_type;
    if (ret_flags != NULL)
	*ret_flags = ctx->mech_flags;
    if (time_rec != NULL)
	*time_rec = ctx->mech_time_rec;

    if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) {
	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
 	return ret;
    }

    _gss_spnego_internal_delete_sec_context(&minor, context_handle,
				   GSS_C_NO_BUFFER);

    return ret;
}
示例#5
0
static OM_uint32 GSSAPI_CALLCONV
acceptor_start
	   (OM_uint32 * minor_status,
	    gss_ctx_id_t * context_handle,
	    const gss_cred_id_t acceptor_cred_handle,
	    const gss_buffer_t input_token_buffer,
	    const gss_channel_bindings_t input_chan_bindings,
	    gss_name_t * src_name,
	    gss_OID * mech_type,
	    gss_buffer_t output_token,
	    OM_uint32 * ret_flags,
	    OM_uint32 * time_rec,
	    gss_cred_id_t *delegated_cred_handle
	   )
{
    OM_uint32 ret, junk;
    NegotiationToken nt;
    size_t nt_len;
    NegTokenInit *ni;
    int i;
    gss_buffer_desc data;
    gss_buffer_t mech_input_token = GSS_C_NO_BUFFER;
    gss_buffer_desc mech_output_token;
    gss_buffer_desc mech_buf;
    gss_OID preferred_mech_type = GSS_C_NO_OID;
    gssspnego_ctx ctx;
    int get_mic = 0;
    int first_ok = 0;

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

    if (input_token_buffer->length == 0)
	return send_supported_mechs (minor_status, output_token);
	
    ret = _gss_spnego_alloc_sec_context(minor_status, context_handle);
    if (ret != GSS_S_COMPLETE)
	return ret;

    ctx = (gssspnego_ctx)*context_handle;

    /*
     * The GSS-API encapsulation is only present on the initial
     * context token (negTokenInit).
     */
    ret = gss_decapsulate_token (input_token_buffer,
				 GSS_SPNEGO_MECHANISM,
				 &data);
    if (ret)
	return ret;

    ret = decode_NegotiationToken(data.value, data.length, &nt, &nt_len);
    gss_release_buffer(minor_status, &data);
    if (ret) {
	*minor_status = ret;
	return GSS_S_DEFECTIVE_TOKEN;
    }
    if (nt.element != choice_NegotiationToken_negTokenInit) {
	*minor_status = 0;
	return GSS_S_DEFECTIVE_TOKEN;
    }
    ni = &nt.u.negTokenInit;

    if (ni->mechTypes.len < 1) {
	free_NegotiationToken(&nt);
	*minor_status = 0;
	return GSS_S_DEFECTIVE_TOKEN;
    }

    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);

    ret = copy_MechTypeList(&ni->mechTypes, &ctx->initiator_mech_types);
    if (ret) {
	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
	free_NegotiationToken(&nt);
	*minor_status = ret;
	return GSS_S_FAILURE;
    }

    /*
     * First we try the opportunistic token if we have support for it,
     * don't try to verify we have credential for the token,
     * gss_accept_sec_context() will (hopefully) tell us that.
     * If that failes,
     */

    ret = select_mech(minor_status,
		      &ni->mechTypes.val[0],
		      0,
		      &preferred_mech_type);

    if (ret == 0 && ni->mechToken != NULL) {
	gss_buffer_desc ibuf;

	ibuf.length = ni->mechToken->length;
	ibuf.value = ni->mechToken->data;
	mech_input_token = &ibuf;

	if (ctx->mech_src_name != GSS_C_NO_NAME)
	    gss_release_name(&junk, &ctx->mech_src_name);
	
	ret = gss_accept_sec_context(minor_status,
				     &ctx->negotiated_ctx_id,
				     acceptor_cred_handle,
				     mech_input_token,
				     input_chan_bindings,
				     &ctx->mech_src_name,
				     &ctx->negotiated_mech_type,
				     &mech_output_token,
				     &ctx->mech_flags,
				     &ctx->mech_time_rec,
				     delegated_cred_handle);

	if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) {
	    ctx->preferred_mech_type = preferred_mech_type;
	    if (ret == GSS_S_COMPLETE)
		ctx->open = 1;

	    ret = acceptor_complete(minor_status,
				    ctx,
				    &get_mic,
				    &mech_buf,
				    mech_input_token,
				    &mech_output_token,
				    ni->mechListMIC,
				    output_token);
	    if (ret != GSS_S_COMPLETE)
		goto out;

	    first_ok = 1;
	} else {
	    gss_mg_collect_error(preferred_mech_type, ret, *minor_status);
	}
    }

    /*
     * If opportunistic token failed, lets try the other mechs.
     */

    if (!first_ok && ni->mechToken != NULL) {

	preferred_mech_type = GSS_C_NO_OID;

	/* Call glue layer to find first mech we support */
	for (i = 1; i < ni->mechTypes.len; ++i) {
	    ret = select_mech(minor_status,
			      &ni->mechTypes.val[i],
			      1,
			      &preferred_mech_type);
	    if (ret == 0)
		break;
	}
	if (preferred_mech_type == GSS_C_NO_OID) {
	    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
	    free_NegotiationToken(&nt);
	    return ret;
	}

	ctx->preferred_mech_type = preferred_mech_type;
    }

    /*
     * The initial token always have a response
     */

    ret = send_accept (minor_status,
		       ctx,
		       &mech_output_token,
		       1,
		       get_mic ? &mech_buf : NULL,
		       output_token);
    if (ret)
	goto out;

out:
    if (mech_output_token.value != NULL)
	gss_release_buffer(&junk, &mech_output_token);
    if (mech_buf.value != NULL) {
	free(mech_buf.value);
	mech_buf.value = NULL;
    }
    free_NegotiationToken(&nt);


    if (ret == GSS_S_COMPLETE) {
	if (src_name != NULL && ctx->mech_src_name != NULL) {
	    spnego_name name;

	    name = calloc(1, sizeof(*name));
	    if (name) {
		name->mech = ctx->mech_src_name;
		ctx->mech_src_name = NULL;
		*src_name = (gss_name_t)name;
	    }
	}
    }

    if (mech_type != NULL)
	*mech_type = ctx->negotiated_mech_type;
    if (ret_flags != NULL)
	*ret_flags = ctx->mech_flags;
    if (time_rec != NULL)
	*time_rec = ctx->mech_time_rec;

    if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) {
	HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
 	return ret;
    }

    _gss_spnego_internal_delete_sec_context(&junk, context_handle,
					    GSS_C_NO_BUFFER);

    return ret;
}
示例#6
0
static void request_respond(struct sockaddr *from, int fromlen, int length, int fd)
{
    CARD16 displayNumber;
    ARRAY16 connectionTypes;
    ARRAYofARRAY8 connectionAddresses;
    ARRAY8 authenticationName;
    ARRAY8 authenticationData;
    ARRAYofARRAY8 authorizationNames;
    ARRAY8 manufacturerDisplayID;
    ARRAY8Ptr reason = 0;
    int expectlen;
    int i, j;
    struct protoDisplay *pdpy;
    ARRAY8 authorizationName, authorizationData;
    ARRAY8Ptr connectionAddress;

    Debug("<request> respond %d\n", length);
    connectionTypes.data = 0;
    connectionAddresses.data = 0;
    authenticationName.data = 0;
    authenticationData.data = 0;
    authorizationNames.data = 0;
    authorizationName.length = 0;
    authorizationData.length = 0;
    manufacturerDisplayID.data = 0;
    if(XdmcpReadCARD16(&buffer, &displayNumber) && XdmcpReadARRAY16(&buffer, &connectionTypes)
       && XdmcpReadARRAYofARRAY8(&buffer, &connectionAddresses) && XdmcpReadARRAY8(&buffer, &authenticationName)
       && XdmcpReadARRAY8(&buffer, &authenticationData) && XdmcpReadARRAYofARRAY8(&buffer, &authorizationNames)
       && XdmcpReadARRAY8(&buffer, &manufacturerDisplayID))
    {
        expectlen = 0;
        expectlen += 2;                              /* displayNumber */
        expectlen += 1 + 2 * connectionTypes.length; /* connectionTypes */
        expectlen += 1;                              /* connectionAddresses */
        for(i = 0; i < (int)connectionAddresses.length; i++)
            expectlen += 2 + connectionAddresses.data[i].length;
        expectlen += 2 + authenticationName.length; /* authenticationName */
        expectlen += 2 + authenticationData.length; /* authenticationData */
        expectlen += 1;                             /* authoriationNames */
        for(i = 0; i < (int)authorizationNames.length; i++)
            expectlen += 2 + authorizationNames.data[i].length;
        expectlen += 2 + manufacturerDisplayID.length; /* displayID */
        if(expectlen != length)
        {
            Debug("<request> length error got %d expect %d\n", length, expectlen);
            goto abort;
        }
        if(connectionTypes.length == 0 || connectionAddresses.length != connectionTypes.length)
        {
            reason = &noValidAddr;
            pdpy = 0;
            goto decline;
        }
        pdpy = FindProtoDisplay((XdmcpNetaddr)from, fromlen, displayNumber);
        if(!pdpy)
        {

            /* Check this Display against the Manager's policy */
            reason = Accept(from, fromlen, displayNumber);
            if(reason)
                goto decline;

            /* Check the Display's stream services against Manager's policy */
            i = SelectConnectionTypeIndex(&connectionTypes, &connectionAddresses);
            if(i < 0)
            {
                reason = &noValidAddr;
                goto decline;
            }

            /* The Manager considers this a new session */
            connectionAddress = &connectionAddresses.data[i];
            pdpy = NewProtoDisplay((XdmcpNetaddr)from, fromlen, displayNumber, connectionTypes.data[i], connectionAddress, NextSessionID());
            Debug("NewProtoDisplay %p\n", pdpy);
            if(!pdpy)
            {
                reason = &outOfMemory;
                goto decline;
            }
        }
        if(authorizationNames.length == 0)
            j = 0;
        else
            j = SelectAuthorizationTypeIndex(&authenticationName, &authorizationNames);
        if(j < 0)
        {
            reason = &noValidAuth;
            goto decline;
        }
        if(!CheckAuthentication(pdpy, &manufacturerDisplayID, &authenticationName, &authenticationData))
        {
            reason = &noAuthentic;
            goto decline;
        }
        if(j < (int)authorizationNames.length)
        {
            Xauth *auth;
            SetProtoDisplayAuthorization(pdpy, (unsigned short)authorizationNames.data[j].length, (char *)authorizationNames.data[j].data);
            auth = pdpy->xdmcpAuthorization;
            if(!auth)
                auth = pdpy->fileAuthorization;
            if(auth)
            {
                authorizationName.length = auth->name_length;
                authorizationName.data = (CARD8Ptr)auth->name;
                authorizationData.length = auth->data_length;
                authorizationData.data = (CARD8Ptr)auth->data;
            }
        }
        if(pdpy)
        {
            send_accept(from, fromlen, pdpy->sessionID, &authenticationName, &authenticationData, &authorizationName, &authorizationData, fd);
        }
        else
        {
        decline:
            send_decline(from, fromlen, &authenticationName, &authenticationData, reason, fd);
            if(pdpy)
                DisposeProtoDisplay(pdpy);
        }
    }
abort:
    XdmcpDisposeARRAY16(&connectionTypes);
    XdmcpDisposeARRAYofARRAY8(&connectionAddresses);
    XdmcpDisposeARRAY8(&authenticationName);
    XdmcpDisposeARRAY8(&authenticationData);
    XdmcpDisposeARRAYofARRAY8(&authorizationNames);
    XdmcpDisposeARRAY8(&manufacturerDisplayID);
}