static int amqp_login_inner(amqp_connection_state_t state, int channel_max, int frame_max, int heartbeat, amqp_sasl_method_enum sasl_method, va_list vl) { struct timeval hb; amqp_method_t method; uint32_t server_frame_max; uint16_t server_channel_max; uint16_t server_heartbeat; if(heartbeat != 0) { hb.tv_sec = 2*heartbeat; hb.tv_usec = 0; (void)setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &hb, sizeof(hb)); (void)setsockopt(state->sockfd, SOL_SOCKET, SO_SNDTIMEO, &hb, sizeof(hb)); } amqp_send_header(state); (void)AMQP_CHECK_EOF_RESULT(amqp_simple_wait_method(state, 0, AMQP_CONNECTION_START_METHOD, &method)); { amqp_connection_start_t *s = (amqp_connection_start_t *) method.decoded; if ((s->version_major != AMQP_PROTOCOL_VERSION_MAJOR) || (s->version_minor != AMQP_PROTOCOL_VERSION_MINOR)) { return -EPROTOTYPE; } /* TODO: check that our chosen SASL mechanism is in the list of acceptable mechanisms. Or even let the application choose from the list! */ } { amqp_bytes_t response_bytes = sasl_response(&state->decoding_pool, sasl_method, vl); amqp_connection_start_ok_t s = (amqp_connection_start_ok_t) { .client_properties = {.num_entries = 0, .entries = NULL}, .mechanism = sasl_method_name(sasl_method), .response = response_bytes, .locale = {.len = 5, .bytes = "en_US"} }; (void)AMQP_CHECK_RESULT(amqp_send_method(state, 0, AMQP_CONNECTION_START_OK_METHOD, &s)); }
static void pro_message_available (PROFILE_INSTANCE *pi) { int result, size; char *buffer, *payload, *response; FRAME *f; struct configobj *appconfig = bp_get_config (pi -> channel -> conn); PRO_LOCALDATA *il = (PRO_LOCALDATA *) pi -> user_ptr1; result = SASL_ALREADY_DONE; if (!(f = bpc_query_message (pi -> channel, BLU_QUERY_ANYTYPE, BLU_QUERY_ANYMSG, BLU_QUERY_ANYANS))) return; if (pro_debug) { fprintf (stderr, "%s message_available: type=%c number=%ld answer=%ld size=%ld\n", pro_name (pi -> channel -> profile_registration -> uri), f -> msg_type, f -> message_number, f -> answer_number, f -> size); fprintf (stderr, f -> size > 150 ? "%-150.150s...\n" : "%s\n", f -> payload); fflush (stderr); } size = bpc_frame_aggregate (pi -> channel, f, &buffer); if (buffer == NULL) { bp_log (pi -> channel -> conn, LOG_PROF, 5, "%s message_available: out of memory aggregating message", pro_name (pi -> channel -> profile_registration -> uri)); bpc_frame_destroy (pi -> channel, f); return; } switch (il -> pl_task) { case PRO_CLIENT_ANON: break; case PRO_CLIENT_OTP: if (il -> pl_sent != 2) break; if (strstr (buffer, "<error") != NULL) sasl_error (pi, buffer, size); else { parse_blob (buffer, &il -> pl_sdb); if (!strcmp (il -> pl_sdb.parse_blob_status, "complete")) sasl_set_local_success (pi); else sasl_set_local_failure (pi, NULL); } break; case PRO_SERVER_ANON: if (il -> pl_sent != 0) break; if ((result = sasl_anonymous_server_guts (buffer, &il -> pl_sdb)) == SASL_COMPLETE) config_set (appconfig, SASL_REMOTE_USERNAME, il -> pl_sdb.parse_blob_data); break; case PRO_SERVER_OTP: switch (il -> pl_sent) { case 0: result = sasl_otp_server_guts_1 (buffer, &il -> pl_sdb); break; case 1: if ((result = sasl_otp_server_guts_2 (buffer, &il -> pl_sdb)) == SASL_COMPLETE) { config_set (appconfig, SASL_REMOTE_USERNAME, il -> pl_sdb.authenID); config_set (appconfig, SASL_REMOTE_TARGET, (il -> pl_sdb.authorID[0] != '\0') ? il -> pl_sdb.authorID : il -> pl_sdb.authenID); } break; } break; } bpc_buffer_destroy (pi -> channel, buffer); switch (il -> pl_task) { case PRO_CLIENT_ANON: case PRO_CLIENT_OTP: response = NULL; break; case PRO_SERVER_ANON: case PRO_SERVER_OTP: response = sasl_response (pi, result); break; } if (f -> msg_type == BLU_FRAME_TYPE_MSG) { payload = response ? response : "<error code='521'>Client-side only</error>"; size = strlen (payload) + sizeof DEFAULT_CONTENT_TYPE - 1; if ((buffer = bpc_buffer_allocate(pi -> channel, size)) != NULL) { sprintf (buffer, "%s%s", DEFAULT_CONTENT_TYPE, payload); bpc_send (pi -> channel, (payload[1] == 'e') ? BLU_FRAME_TYPE_ERR : BLU_FRAME_TYPE_RPY, f -> message_number, f -> answer_number, BLU_FRAME_COMPLETE, buffer, size); il -> pl_sent++; } else bp_log (pi -> channel -> conn, LOG_PROF, 5, "%s message: out of memory sending response", pro_name (pi -> channel -> profile_registration -> uri)); } bpc_frame_destroy (pi -> channel, f); }
static int amqp_login_inner(amqp_connection_state_t state, int channel_max, int frame_max, int heartbeat, amqp_sasl_method_enum sasl_method, va_list vl) { int res; amqp_method_t method; int server_frame_max; uint16_t server_channel_max; uint16_t server_heartbeat; amqp_send_header(state); res = amqp_simple_wait_method(state, 0, AMQP_CONNECTION_START_METHOD, &method); if (res < 0) return res; { amqp_connection_start_t *s = (amqp_connection_start_t *) method.decoded; if ((s->version_major != AMQP_PROTOCOL_VERSION_MAJOR) || (s->version_minor != AMQP_PROTOCOL_VERSION_MINOR)) { return -ERROR_INCOMPATIBLE_AMQP_VERSION; } /* TODO: check that our chosen SASL mechanism is in the list of acceptable mechanisms. Or even let the application choose from the list! */ } { amqp_table_entry_t properties[2]; amqp_connection_start_ok_t s; amqp_bytes_t response_bytes = sasl_response(&state->decoding_pool, sasl_method, vl); if (response_bytes.bytes == NULL) return -ERROR_NO_MEMORY; properties[0].key = amqp_cstring_bytes("product"); properties[0].value.kind = AMQP_FIELD_KIND_UTF8; properties[0].value.value.bytes = amqp_cstring_bytes("rabbitmq-c"); properties[1].key = amqp_cstring_bytes("information"); properties[1].value.kind = AMQP_FIELD_KIND_UTF8; properties[1].value.value.bytes = amqp_cstring_bytes("See http://hg.rabbitmq.com/rabbitmq-c/"); s.client_properties.num_entries = 2; s.client_properties.entries = properties; s.mechanism = sasl_method_name(sasl_method); s.response = response_bytes; s.locale.bytes = "en_US"; s.locale.len = 5; res = amqp_send_method(state, 0, AMQP_CONNECTION_START_OK_METHOD, &s); if (res < 0) return res; } amqp_release_buffers(state); res = amqp_simple_wait_method(state, 0, AMQP_CONNECTION_TUNE_METHOD, &method); if (res < 0) return res; { amqp_connection_tune_t *s = (amqp_connection_tune_t *) method.decoded; server_channel_max = s->channel_max; server_frame_max = s->frame_max; server_heartbeat = s->heartbeat; } if (server_channel_max != 0 && server_channel_max < channel_max) channel_max = server_channel_max; if (server_frame_max != 0 && server_frame_max < frame_max) frame_max = server_frame_max; if (server_heartbeat != 0 && server_heartbeat < heartbeat) heartbeat = server_heartbeat; res = amqp_tune_connection(state, channel_max, frame_max, heartbeat); if (res < 0) return res; { amqp_connection_tune_ok_t s; s.frame_max = frame_max; s.channel_max = channel_max; s.heartbeat = heartbeat; res = amqp_send_method(state, 0, AMQP_CONNECTION_TUNE_OK_METHOD, &s); if (res < 0) return res; } amqp_release_buffers(state); return 0; }
static void pro_start_indication (PROFILE_INSTANCE *pi, PROFILE *po) { char *cp, *otp; DIAGNOSTIC ds, *d = &ds; PRO_LOCALDATA *il; PROFILE ps, *p = &ps; struct configobj *appconfig = bp_get_config (pi -> channel -> conn); struct cfgsearchobj *cs; if (pro_debug) { fprintf (stderr, "%s start_indication: piggyback=\"%s\"\n", pro_name (po -> uri), po -> piggyback ? po -> piggyback : "<NULL>"); fflush (stderr); } memset (p, 0, sizeof *p); p -> uri = po -> uri; memset (d, 0, sizeof *d); d -> code = 421; if (((cp = config_get (appconfig, SASL_LOCAL_CODE)) != NULL) && (*cp == '2')) { d -> code = 520; d -> message = "already tuned for authentication"; bpc_start_response (pi -> channel, p, d); return; } if (!(il = (PRO_LOCALDATA *) lib_malloc (sizeof *il))) { d -> message = "out of memory"; bpc_start_response (pi -> channel, p, d); return; } pi -> user_ptr1 = il; memset (il, 0, sizeof *il); if (!(otp = config_get (appconfig, SASL_OTP_URI))) otp = PRO_OTP_URI; il -> pl_task = strcmp (po -> uri, otp) ? PRO_SERVER_ANON : PRO_SERVER_OTP; if (!(il -> pl_sdb.path = config_get (appconfig, SASL_OTP_DIRECTORY))) il -> pl_sdb.path = "/tmp"; cs = config_search_init (appconfig, SASL_REMOTE_PREFIX, ""); for (cp = config_search_string_firstkey (cs); cp; cp = config_search_string_nextkey (cs)) config_delete (appconfig, cp); config_search_fin (&cs); switch (il -> pl_task) { case PRO_SERVER_ANON: config_set (appconfig, SASL_REMOTE_MECHANISM, "anonymous"); break; case PRO_SERVER_OTP: config_set (appconfig, SASL_REMOTE_MECHANISM, "otp"); break; } if (po -> piggyback_length > 0) { int result; switch (il -> pl_task) { case PRO_SERVER_ANON: if ((result = sasl_anonymous_server_guts (po -> piggyback, &il -> pl_sdb)) == SASL_COMPLETE) config_set (appconfig, SASL_REMOTE_USERNAME, il -> pl_sdb.parse_blob_data); break; case PRO_SERVER_OTP: result = sasl_otp_server_guts_1 (po -> piggyback, &il -> pl_sdb); break; } p -> piggyback_length = strlen (p -> piggyback = sasl_response (pi, result)); il -> pl_sent = 1; } bpc_start_response (pi -> channel, p, NULL); }