bool default_sasl_process_mechanisms()

in c/src/sasl/default_sasl.c [97:179]


bool default_sasl_process_mechanisms(pn_transport_t *transport, const char *mechs)
{
  const char *username = pnx_sasl_get_username(transport);
  const char *password = pnx_sasl_get_password(transport);
  const char *authzid  = pnx_sasl_get_authorization(transport);

  // Check whether offered EXTERNAL, PLAIN or ANONYMOUS
  // Look for "EXTERNAL" in mechs
  const char *found = strstr(mechs, EXTERNAL);
  // Make sure that string is separated and terminated
  if (found && (found==mechs || found[-1]==' ') && (found[8]==0 || found[8]==' ')) {
    pnx_sasl_set_selected_mechanism(transport, EXTERNAL);
    if (authzid) {
      size_t size = strlen(authzid);
      char *iresp = (char *) malloc(size);
      if (!iresp) return false;

      pnx_sasl_set_context(transport, iresp);

      memmove(iresp, authzid, size);
      pnx_sasl_set_bytes_out(transport, pn_bytes(size, iresp));
    } else {
      static const char empty[] = "";
      pnx_sasl_set_bytes_out(transport, pn_bytes(0, empty));
    }
    pnx_sasl_set_desired_state(transport, SASL_POSTED_INIT);
    return true;
  }

  // Look for "PLAIN" in mechs
  found = strstr(mechs, PLAIN);
  // Make sure that string is separated and terminated, allowed
  // and we have a username and password and connection is encrypted or we allow insecure
  if (found && (found==mechs || found[-1]==' ') && (found[5]==0 || found[5]==' ') &&
      (pnx_sasl_is_transport_encrypted(transport) || pnx_sasl_get_allow_insecure_mechanisms(transport)) &&
      username && password) {
    pnx_sasl_set_selected_mechanism(transport, PLAIN);
    size_t zsize = authzid ? strlen(authzid) : 0;
    size_t usize = strlen(username);
    size_t psize = strlen(password);
    size_t size = zsize + usize + psize + 2;
    char *iresp = (char *) malloc(size);
    if (!iresp) return false;

    pnx_sasl_set_context(transport, iresp);

    if (authzid) memmove(&iresp[0], authzid, zsize);
    iresp[zsize] = 0;
    memmove(&iresp[zsize + 1], username, usize);
    iresp[zsize + usize + 1] = 0;
    memmove(&iresp[zsize + usize + 2], password, psize);
    pnx_sasl_set_bytes_out(transport, pn_bytes(size, iresp));

    // Zero out password and dealloc
    pnx_sasl_clear_password(transport);

    pnx_sasl_set_desired_state(transport, SASL_POSTED_INIT);
    return true;
  }

  // Look for "ANONYMOUS" in mechs
  found = strstr(mechs, ANONYMOUS);
  // Make sure that string is separated and terminated and allowed
  if (found && (found==mechs || found[-1]==' ') && (found[9]==0 || found[9]==' ')) {
    pnx_sasl_set_selected_mechanism(transport, ANONYMOUS);
    if (username) {
      size_t size = strlen(username);
      char *iresp = (char *) malloc(size);
      if (!iresp) return false;

      pnx_sasl_set_context(transport, iresp);

      memmove(iresp, username, size);
      pnx_sasl_set_bytes_out(transport, pn_bytes(size, iresp));
    } else {
      static const char anon[] = "anonymous";
      pnx_sasl_set_bytes_out(transport, pn_bytes(sizeof anon-1, anon));
    }
    pnx_sasl_set_desired_state(transport, SASL_POSTED_INIT);
    return true;
  }
  return false;
}