static void pni_post_sasl_frame()

in c/src/sasl/sasl.c [485:572]


static void pni_post_sasl_frame(pn_transport_t *transport)
{
  pni_sasl_t *sasl = transport->sasl;
  pn_bytes_t out = sasl->bytes_out;
  enum pnx_sasl_state desired_state = sasl->desired_state;
  while (sasl->desired_state > sasl->last_state) {
    switch (desired_state) {
    case SASL_POSTED_INIT: {
      /* GENERATE_CODEC_CODE: "DL[szS]" */
      pn_bytes_t buf = pn_amqp_encode_DLEszSe(&transport->scratch_space, SASL_INIT, pn_string_bytes(sasl->selected_mechanism), out.size, out.start, pn_string_bytes(sasl->local_fqdn));
      pn_framing_send_sasl(transport, buf);
      pni_emit(transport);
      break;
    }
    case SASL_POSTED_MECHANISMS: {
      // TODO(PROTON-2122) Replace magic number 32 with dynamically sized memory
      char *mechs[32];
      char *mechlist = pn_strdup(pni_sasl_impl_list_mechs(transport));

      int count = 0;
      if (mechlist) {
        pni_split_mechs(mechlist, sasl->included_mechanisms, mechs, &count);
      }
      /* GENERATE_CODEC_CODE: "DL[@T[*s]]" */
      pn_bytes_t buf = pn_amqp_encode_DLEATEjsee(&transport->scratch_space, SASL_MECHANISMS, PN_SYMBOL, count, mechs);
      free(mechlist);
      pn_framing_send_sasl(transport, buf);
      pni_emit(transport);
      break;
    }
    case SASL_POSTED_RESPONSE:
      if (sasl->last_state != SASL_POSTED_RESPONSE) {
        /* "DL[Z]" */
        pn_bytes_t buf = pn_amqp_encode_DLEZe(&transport->scratch_space, SASL_RESPONSE, out.size, out.start);
        pn_framing_send_sasl(transport, buf);
        pni_emit(transport);
      }
      break;
    case SASL_POSTED_CHALLENGE:
      if (sasl->last_state < SASL_POSTED_MECHANISMS) {
        desired_state = SASL_POSTED_MECHANISMS;
        continue;
      } else if (sasl->last_state != SASL_POSTED_CHALLENGE) {
        /* "DL[Z]" */
        pn_bytes_t buf = pn_amqp_encode_DLEZe(&transport->scratch_space, SASL_CHALLENGE, out.size, out.start);
        pn_framing_send_sasl(transport, buf);
        pni_emit(transport);
      }
      break;
    case SASL_POSTED_OUTCOME: {
      if (sasl->last_state < SASL_POSTED_MECHANISMS) {
        desired_state = SASL_POSTED_MECHANISMS;
        continue;
      }
      /* "DL[Bz]" */
      pn_bytes_t buf = pn_amqp_encode_DLEBze(&transport->scratch_space, SASL_OUTCOME, sasl->outcome, out.size, out.start);
      pn_framing_send_sasl(transport, buf);
      pni_emit(transport);
      if (sasl->outcome!=PN_SASL_OK) {
        const char *selected_mechanism = transport->sasl->selected_mechanism ? pn_string_get(transport->sasl->selected_mechanism) : NULL;
        pn_do_error(transport, "amqp:unauthorized-access", "Failed to authenticate client [mech=%s]",
                    selected_mechanism ? selected_mechanism : "none");
        desired_state = SASL_ERROR;
      }
      break;
    }
    case SASL_RECVED_SUCCESS:
      if (sasl->last_state < SASL_POSTED_INIT) {
        desired_state = SASL_POSTED_INIT;
        continue;
      }
      break;
    case SASL_RECVED_FAILURE: {
      const char *selected_mechanism = transport->sasl->selected_mechanism ? pn_string_get(transport->sasl->selected_mechanism) : NULL;
      pn_do_error(transport, "amqp:unauthorized-access", "Authentication failed [mech=%s]",
                  selected_mechanism ? selected_mechanism : "none");
      desired_state = SASL_ERROR;
      break;
    }
    case SASL_ERROR:
      break;
    case SASL_NONE:
      return;
    }
    sasl->last_state = desired_state;
    desired_state = sasl->desired_state;
  }
}