A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Sun Apr 24 16:40:31 2016 -0700
Revision:
1:eab586236bfe
Parent:
0:6ae2f7bca550
Child:
5:ae49385aff34
1.0.5

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Azure.IoT Build 0:6ae2f7bca550 1 // Copyright (c) Microsoft. All rights reserved.
Azure.IoT Build 0:6ae2f7bca550 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
Azure.IoT Build 0:6ae2f7bca550 3
Azure.IoT Build 0:6ae2f7bca550 4 #include <stdlib.h>
Azure.IoT Build 0:6ae2f7bca550 5 #ifdef _CRTDBG_MAP_ALLOC
Azure.IoT Build 0:6ae2f7bca550 6 #include <crtdbg.h>
Azure.IoT Build 0:6ae2f7bca550 7 #endif
Azure.IoT Build 0:6ae2f7bca550 8 #include <stddef.h>
Azure.IoT Build 0:6ae2f7bca550 9 #include <stdio.h>
Azure.IoT Build 0:6ae2f7bca550 10 #include <string.h>
Azure.IoT Build 0:6ae2f7bca550 11 #include "azure_uamqp_c/saslclientio.h"
Azure.IoT Build 0:6ae2f7bca550 12 #include "azure_c_shared_utility/xio.h"
Azure.IoT Build 0:6ae2f7bca550 13 #include "azure_c_shared_utility/xlogging.h"
Azure.IoT Build 0:6ae2f7bca550 14 #include "azure_uamqp_c/amqpalloc.h"
Azure.IoT Build 0:6ae2f7bca550 15 #include "azure_uamqp_c/frame_codec.h"
Azure.IoT Build 0:6ae2f7bca550 16 #include "azure_uamqp_c/sasl_frame_codec.h"
Azure.IoT Build 0:6ae2f7bca550 17 #include "azure_uamqp_c/amqp_definitions.h"
Azure.IoT Build 0:6ae2f7bca550 18 #include "azure_uamqp_c/amqpvalue_to_string.h"
Azure.IoT Build 0:6ae2f7bca550 19
Azure.IoT Build 0:6ae2f7bca550 20 typedef enum IO_STATE_TAG
Azure.IoT Build 0:6ae2f7bca550 21 {
Azure.IoT Build 0:6ae2f7bca550 22 IO_STATE_NOT_OPEN,
Azure.IoT Build 0:6ae2f7bca550 23 IO_STATE_OPENING_UNDERLYING_IO,
Azure.IoT Build 0:6ae2f7bca550 24 IO_STATE_SASL_HANDSHAKE,
Azure.IoT Build 0:6ae2f7bca550 25 IO_STATE_OPEN,
Azure.IoT Build 0:6ae2f7bca550 26 IO_STATE_CLOSING,
Azure.IoT Build 0:6ae2f7bca550 27 IO_STATE_ERROR
Azure.IoT Build 0:6ae2f7bca550 28 } IO_STATE;
Azure.IoT Build 0:6ae2f7bca550 29
Azure.IoT Build 0:6ae2f7bca550 30 typedef enum SASL_HEADER_EXCHANGE_STATE_TAG
Azure.IoT Build 0:6ae2f7bca550 31 {
Azure.IoT Build 0:6ae2f7bca550 32 SASL_HEADER_EXCHANGE_IDLE,
Azure.IoT Build 0:6ae2f7bca550 33 SASL_HEADER_EXCHANGE_HEADER_SENT,
Azure.IoT Build 0:6ae2f7bca550 34 SASL_HEADER_EXCHANGE_HEADER_RCVD,
Azure.IoT Build 0:6ae2f7bca550 35 SASL_HEADER_EXCHANGE_HEADER_EXCH
Azure.IoT Build 0:6ae2f7bca550 36 } SASL_HEADER_EXCHANGE_STATE;
Azure.IoT Build 0:6ae2f7bca550 37
Azure.IoT Build 0:6ae2f7bca550 38 typedef enum SASL_CLIENT_NEGOTIATION_STATE_TAG
Azure.IoT Build 0:6ae2f7bca550 39 {
Azure.IoT Build 0:6ae2f7bca550 40 SASL_CLIENT_NEGOTIATION_NOT_STARTED,
Azure.IoT Build 0:6ae2f7bca550 41 SASL_CLIENT_NEGOTIATION_MECH_RCVD,
Azure.IoT Build 0:6ae2f7bca550 42 SASL_CLIENT_NEGOTIATION_INIT_SENT,
Azure.IoT Build 0:6ae2f7bca550 43 SASL_CLIENT_NEGOTIATION_CHALLENGE_RCVD,
Azure.IoT Build 0:6ae2f7bca550 44 SASL_CLIENT_NEGOTIATION_RESPONSE_SENT,
Azure.IoT Build 0:6ae2f7bca550 45 SASL_CLIENT_NEGOTIATION_OUTCOME_RCVD,
Azure.IoT Build 0:6ae2f7bca550 46 SASL_CLIENT_NEGOTIATION_ERROR
Azure.IoT Build 0:6ae2f7bca550 47 } SASL_CLIENT_NEGOTIATION_STATE;
Azure.IoT Build 0:6ae2f7bca550 48
Azure.IoT Build 0:6ae2f7bca550 49 typedef struct SASL_CLIENT_IO_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 50 {
Azure.IoT Build 0:6ae2f7bca550 51 XIO_HANDLE underlying_io;
Azure.IoT Build 0:6ae2f7bca550 52 ON_BYTES_RECEIVED on_bytes_received;
Azure.IoT Build 0:6ae2f7bca550 53 ON_IO_OPEN_COMPLETE on_io_open_complete;
Azure.IoT Build 0:6ae2f7bca550 54 ON_IO_CLOSE_COMPLETE on_io_close_complete;
Azure.IoT Build 0:6ae2f7bca550 55 ON_IO_ERROR on_io_error;
Azure.IoT Build 0:6ae2f7bca550 56 void* on_bytes_received_context;
Azure.IoT Build 0:6ae2f7bca550 57 void* on_io_open_complete_context;
Azure.IoT Build 0:6ae2f7bca550 58 void* on_io_close_complete_context;
Azure.IoT Build 0:6ae2f7bca550 59 void* on_io_error_context;
Azure.IoT Build 0:6ae2f7bca550 60 LOGGER_LOG logger_log;
Azure.IoT Build 0:6ae2f7bca550 61 SASL_HEADER_EXCHANGE_STATE sasl_header_exchange_state;
Azure.IoT Build 0:6ae2f7bca550 62 SASL_CLIENT_NEGOTIATION_STATE sasl_client_negotiation_state;
Azure.IoT Build 0:6ae2f7bca550 63 size_t header_bytes_received;
Azure.IoT Build 0:6ae2f7bca550 64 SASL_FRAME_CODEC_HANDLE sasl_frame_codec;
Azure.IoT Build 0:6ae2f7bca550 65 FRAME_CODEC_HANDLE frame_codec;
Azure.IoT Build 0:6ae2f7bca550 66 IO_STATE io_state;
Azure.IoT Build 0:6ae2f7bca550 67 SASL_MECHANISM_HANDLE sasl_mechanism;
Azure.IoT Build 0:6ae2f7bca550 68 } SASL_CLIENT_IO_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 69
Azure.IoT Build 0:6ae2f7bca550 70 /* Codes_SRS_SASLCLIENTIO_01_002: [The protocol header consists of the upper case ASCII letters “AMQP” followed by a protocol id of three, followed by three unsigned bytes representing the major, minor, and revision of the specification version (currently 1 (SASL-MAJOR), 0 (SASLMINOR), 0 (SASL-REVISION)).] */
Azure.IoT Build 0:6ae2f7bca550 71 /* Codes_SRS_SASLCLIENTIO_01_124: [SASL-MAJOR 1 major protocol version.] */
Azure.IoT Build 0:6ae2f7bca550 72 /* Codes_SRS_SASLCLIENTIO_01_125: [SASL-MINOR 0 minor protocol version.] */
Azure.IoT Build 0:6ae2f7bca550 73 /* Codes_SRS_SASLCLIENTIO_01_126: [SASL-REVISION 0 protocol revision.] */
Azure.IoT Build 0:6ae2f7bca550 74 const unsigned char sasl_header[] = { 'A', 'M', 'Q', 'P', 3, 1, 0, 0 };
Azure.IoT Build 0:6ae2f7bca550 75
Azure.IoT Build 0:6ae2f7bca550 76 static void indicate_error(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance)
Azure.IoT Build 0:6ae2f7bca550 77 {
Azure.IoT Build 0:6ae2f7bca550 78 if (sasl_client_io_instance->on_io_error != NULL)
Azure.IoT Build 0:6ae2f7bca550 79 {
Azure.IoT Build 0:6ae2f7bca550 80 sasl_client_io_instance->on_io_error(sasl_client_io_instance->on_io_error_context);
Azure.IoT Build 0:6ae2f7bca550 81 }
Azure.IoT Build 0:6ae2f7bca550 82 }
Azure.IoT Build 0:6ae2f7bca550 83
Azure.IoT Build 0:6ae2f7bca550 84 static void indicate_open_complete(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance, IO_OPEN_RESULT open_result)
Azure.IoT Build 0:6ae2f7bca550 85 {
Azure.IoT Build 0:6ae2f7bca550 86 if (sasl_client_io_instance->on_io_open_complete != NULL)
Azure.IoT Build 0:6ae2f7bca550 87 {
Azure.IoT Build 0:6ae2f7bca550 88 sasl_client_io_instance->on_io_open_complete(sasl_client_io_instance->on_io_open_complete_context, open_result);
Azure.IoT Build 0:6ae2f7bca550 89 }
Azure.IoT Build 0:6ae2f7bca550 90 }
Azure.IoT Build 0:6ae2f7bca550 91
Azure.IoT Build 0:6ae2f7bca550 92 static void indicate_close_complete(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance)
Azure.IoT Build 0:6ae2f7bca550 93 {
Azure.IoT Build 0:6ae2f7bca550 94 if (sasl_client_io_instance->on_io_close_complete != NULL)
Azure.IoT Build 0:6ae2f7bca550 95 {
Azure.IoT Build 0:6ae2f7bca550 96 sasl_client_io_instance->on_io_close_complete(sasl_client_io_instance->on_io_close_complete_context);
Azure.IoT Build 0:6ae2f7bca550 97 }
Azure.IoT Build 0:6ae2f7bca550 98 }
Azure.IoT Build 0:6ae2f7bca550 99
Azure.IoT Build 0:6ae2f7bca550 100 static void on_underlying_io_close_complete(void* context)
Azure.IoT Build 0:6ae2f7bca550 101 {
Azure.IoT Build 0:6ae2f7bca550 102 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 103
Azure.IoT Build 0:6ae2f7bca550 104 switch (sasl_client_io_instance->io_state)
Azure.IoT Build 0:6ae2f7bca550 105 {
Azure.IoT Build 0:6ae2f7bca550 106 default:
Azure.IoT Build 0:6ae2f7bca550 107 break;
Azure.IoT Build 0:6ae2f7bca550 108
Azure.IoT Build 0:6ae2f7bca550 109 case IO_STATE_OPENING_UNDERLYING_IO:
Azure.IoT Build 0:6ae2f7bca550 110 case IO_STATE_SASL_HANDSHAKE:
Azure.IoT Build 0:6ae2f7bca550 111 sasl_client_io_instance->io_state = IO_STATE_NOT_OPEN;
Azure.IoT Build 0:6ae2f7bca550 112 indicate_open_complete(sasl_client_io_instance, IO_OPEN_ERROR);
Azure.IoT Build 0:6ae2f7bca550 113 break;
Azure.IoT Build 0:6ae2f7bca550 114
Azure.IoT Build 0:6ae2f7bca550 115 case IO_STATE_CLOSING:
Azure.IoT Build 0:6ae2f7bca550 116 sasl_client_io_instance->io_state = IO_STATE_NOT_OPEN;
Azure.IoT Build 0:6ae2f7bca550 117 indicate_close_complete(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 118 break;
Azure.IoT Build 0:6ae2f7bca550 119 }
Azure.IoT Build 0:6ae2f7bca550 120 }
Azure.IoT Build 0:6ae2f7bca550 121
Azure.IoT Build 0:6ae2f7bca550 122 static void handle_error(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance)
Azure.IoT Build 0:6ae2f7bca550 123 {
Azure.IoT Build 0:6ae2f7bca550 124 switch (sasl_client_io_instance->io_state)
Azure.IoT Build 0:6ae2f7bca550 125 {
Azure.IoT Build 0:6ae2f7bca550 126 default:
Azure.IoT Build 0:6ae2f7bca550 127 case IO_STATE_NOT_OPEN:
Azure.IoT Build 0:6ae2f7bca550 128 break;
Azure.IoT Build 0:6ae2f7bca550 129
Azure.IoT Build 0:6ae2f7bca550 130 case IO_STATE_OPENING_UNDERLYING_IO:
Azure.IoT Build 0:6ae2f7bca550 131 case IO_STATE_SASL_HANDSHAKE:
Azure.IoT Build 0:6ae2f7bca550 132 if (xio_close(sasl_client_io_instance->underlying_io, on_underlying_io_close_complete, sasl_client_io_instance) != 0)
Azure.IoT Build 0:6ae2f7bca550 133 {
Azure.IoT Build 0:6ae2f7bca550 134 sasl_client_io_instance->io_state = IO_STATE_NOT_OPEN;
Azure.IoT Build 0:6ae2f7bca550 135 indicate_open_complete(sasl_client_io_instance, IO_OPEN_ERROR);
Azure.IoT Build 0:6ae2f7bca550 136 }
Azure.IoT Build 0:6ae2f7bca550 137 break;
Azure.IoT Build 0:6ae2f7bca550 138
Azure.IoT Build 0:6ae2f7bca550 139 case IO_STATE_OPEN:
Azure.IoT Build 0:6ae2f7bca550 140 sasl_client_io_instance->io_state = IO_STATE_ERROR;
Azure.IoT Build 0:6ae2f7bca550 141 indicate_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 142 break;
Azure.IoT Build 0:6ae2f7bca550 143 }
Azure.IoT Build 0:6ae2f7bca550 144 }
Azure.IoT Build 0:6ae2f7bca550 145
Azure.IoT Build 0:6ae2f7bca550 146 static int send_sasl_header(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance)
Azure.IoT Build 0:6ae2f7bca550 147 {
Azure.IoT Build 0:6ae2f7bca550 148 int result;
Azure.IoT Build 0:6ae2f7bca550 149
Azure.IoT Build 0:6ae2f7bca550 150 /* Codes_SRS_SASLCLIENTIO_01_078: [SASL client IO shall start the header exchange by sending the SASL header.] */
Azure.IoT Build 0:6ae2f7bca550 151 /* Codes_SRS_SASLCLIENTIO_01_095: [Sending the header shall be done by using xio_send.] */
Azure.IoT Build 0:6ae2f7bca550 152 if (xio_send(sasl_client_io_instance->underlying_io, sasl_header, sizeof(sasl_header), NULL, NULL) != 0)
Azure.IoT Build 0:6ae2f7bca550 153 {
Azure.IoT Build 0:6ae2f7bca550 154 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 155 }
Azure.IoT Build 0:6ae2f7bca550 156 else
Azure.IoT Build 0:6ae2f7bca550 157 {
Azure.IoT Build 0:6ae2f7bca550 158 LOG(sasl_client_io_instance->logger_log, LOG_LINE, "-> Header (AMQP 3.1.0.0)");
Azure.IoT Build 0:6ae2f7bca550 159
Azure.IoT Build 0:6ae2f7bca550 160 result = 0;
Azure.IoT Build 0:6ae2f7bca550 161 }
Azure.IoT Build 0:6ae2f7bca550 162
Azure.IoT Build 0:6ae2f7bca550 163 return result;
Azure.IoT Build 0:6ae2f7bca550 164 }
Azure.IoT Build 0:6ae2f7bca550 165
Azure.IoT Build 0:6ae2f7bca550 166 static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT open_result)
Azure.IoT Build 0:6ae2f7bca550 167 {
Azure.IoT Build 0:6ae2f7bca550 168 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 169
Azure.IoT Build 0:6ae2f7bca550 170 switch (sasl_client_io_instance->io_state)
Azure.IoT Build 0:6ae2f7bca550 171 {
Azure.IoT Build 0:6ae2f7bca550 172 default:
Azure.IoT Build 0:6ae2f7bca550 173 break;
Azure.IoT Build 0:6ae2f7bca550 174
Azure.IoT Build 0:6ae2f7bca550 175 case IO_STATE_OPENING_UNDERLYING_IO:
Azure.IoT Build 0:6ae2f7bca550 176 if (open_result == IO_OPEN_OK)
Azure.IoT Build 0:6ae2f7bca550 177 {
Azure.IoT Build 0:6ae2f7bca550 178 sasl_client_io_instance->io_state = IO_STATE_SASL_HANDSHAKE;
Azure.IoT Build 0:6ae2f7bca550 179 if (sasl_client_io_instance->sasl_header_exchange_state != SASL_HEADER_EXCHANGE_IDLE)
Azure.IoT Build 0:6ae2f7bca550 180 {
Azure.IoT Build 0:6ae2f7bca550 181 /* Codes_SRS_SASLCLIENTIO_01_116: [Any underlying IO state changes to state OPEN after the header exchange has been started shall trigger no action.] */
Azure.IoT Build 0:6ae2f7bca550 182 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 183 }
Azure.IoT Build 0:6ae2f7bca550 184 else
Azure.IoT Build 0:6ae2f7bca550 185 {
Azure.IoT Build 0:6ae2f7bca550 186 /* Codes_SRS_SASLCLIENTIO_01_105: [start header exchange] */
Azure.IoT Build 0:6ae2f7bca550 187 /* Codes_SRS_SASLCLIENTIO_01_001: [To establish a SASL layer, each peer MUST start by sending a protocol header.] */
Azure.IoT Build 0:6ae2f7bca550 188 if (send_sasl_header(sasl_client_io_instance) != 0)
Azure.IoT Build 0:6ae2f7bca550 189 {
Azure.IoT Build 0:6ae2f7bca550 190 /* Codes_SRS_SASLCLIENTIO_01_073: [If the handshake fails (i.e. the outcome is an error) the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 191 /* Codes_SRS_SASLCLIENTIO_01_077: [If sending the SASL header fails, the SASL client IO state shall be set to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 192 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 193 }
Azure.IoT Build 0:6ae2f7bca550 194 else
Azure.IoT Build 0:6ae2f7bca550 195 {
Azure.IoT Build 0:6ae2f7bca550 196 sasl_client_io_instance->sasl_header_exchange_state = SASL_HEADER_EXCHANGE_HEADER_SENT;
Azure.IoT Build 0:6ae2f7bca550 197 }
Azure.IoT Build 0:6ae2f7bca550 198 }
Azure.IoT Build 0:6ae2f7bca550 199 }
Azure.IoT Build 0:6ae2f7bca550 200 else
Azure.IoT Build 0:6ae2f7bca550 201 {
Azure.IoT Build 0:6ae2f7bca550 202 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 203 }
Azure.IoT Build 0:6ae2f7bca550 204
Azure.IoT Build 0:6ae2f7bca550 205 break;
Azure.IoT Build 0:6ae2f7bca550 206 }
Azure.IoT Build 0:6ae2f7bca550 207 }
Azure.IoT Build 0:6ae2f7bca550 208
Azure.IoT Build 0:6ae2f7bca550 209 static void on_underlying_io_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 210 {
Azure.IoT Build 0:6ae2f7bca550 211 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 212
Azure.IoT Build 0:6ae2f7bca550 213 switch (sasl_client_io_instance->io_state)
Azure.IoT Build 0:6ae2f7bca550 214 {
Azure.IoT Build 0:6ae2f7bca550 215 default:
Azure.IoT Build 0:6ae2f7bca550 216 break;
Azure.IoT Build 0:6ae2f7bca550 217
Azure.IoT Build 0:6ae2f7bca550 218 case IO_STATE_OPENING_UNDERLYING_IO:
Azure.IoT Build 0:6ae2f7bca550 219 case IO_STATE_SASL_HANDSHAKE:
Azure.IoT Build 0:6ae2f7bca550 220 sasl_client_io_instance->io_state = IO_STATE_NOT_OPEN;
Azure.IoT Build 0:6ae2f7bca550 221 indicate_open_complete(sasl_client_io_instance, IO_OPEN_ERROR);
Azure.IoT Build 0:6ae2f7bca550 222 break;
Azure.IoT Build 0:6ae2f7bca550 223
Azure.IoT Build 0:6ae2f7bca550 224 case IO_STATE_OPEN:
Azure.IoT Build 0:6ae2f7bca550 225 sasl_client_io_instance->io_state = IO_STATE_ERROR;
Azure.IoT Build 0:6ae2f7bca550 226 indicate_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 227 break;
Azure.IoT Build 0:6ae2f7bca550 228 }
Azure.IoT Build 0:6ae2f7bca550 229 }
Azure.IoT Build 0:6ae2f7bca550 230
Azure.IoT Build 0:6ae2f7bca550 231 static const char* get_frame_type_as_string(AMQP_VALUE descriptor)
Azure.IoT Build 0:6ae2f7bca550 232 {
Azure.IoT Build 0:6ae2f7bca550 233 const char* result;
Azure.IoT Build 0:6ae2f7bca550 234
Azure.IoT Build 0:6ae2f7bca550 235 if (is_sasl_mechanisms_type_by_descriptor(descriptor))
Azure.IoT Build 0:6ae2f7bca550 236 {
Azure.IoT Build 0:6ae2f7bca550 237 result = "[SASL MECHANISMS]";
Azure.IoT Build 0:6ae2f7bca550 238 }
Azure.IoT Build 0:6ae2f7bca550 239 else if (is_sasl_init_type_by_descriptor(descriptor))
Azure.IoT Build 0:6ae2f7bca550 240 {
Azure.IoT Build 0:6ae2f7bca550 241 result = "[SASL INIT]";
Azure.IoT Build 0:6ae2f7bca550 242 }
Azure.IoT Build 0:6ae2f7bca550 243 else if (is_sasl_challenge_type_by_descriptor(descriptor))
Azure.IoT Build 0:6ae2f7bca550 244 {
Azure.IoT Build 0:6ae2f7bca550 245 result = "[SASL CHALLENGE]";
Azure.IoT Build 0:6ae2f7bca550 246 }
Azure.IoT Build 0:6ae2f7bca550 247 else if (is_sasl_response_type_by_descriptor(descriptor))
Azure.IoT Build 0:6ae2f7bca550 248 {
Azure.IoT Build 0:6ae2f7bca550 249 result = "[SASL RESPONSE]";
Azure.IoT Build 0:6ae2f7bca550 250 }
Azure.IoT Build 0:6ae2f7bca550 251 else if (is_sasl_outcome_type_by_descriptor(descriptor))
Azure.IoT Build 0:6ae2f7bca550 252 {
Azure.IoT Build 0:6ae2f7bca550 253 result = "[SASL OUTCOME]";
Azure.IoT Build 0:6ae2f7bca550 254 }
Azure.IoT Build 0:6ae2f7bca550 255 else
Azure.IoT Build 0:6ae2f7bca550 256 {
Azure.IoT Build 0:6ae2f7bca550 257 result = "[Unknown]";
Azure.IoT Build 0:6ae2f7bca550 258 }
Azure.IoT Build 0:6ae2f7bca550 259
Azure.IoT Build 0:6ae2f7bca550 260 return result;
Azure.IoT Build 0:6ae2f7bca550 261 }
Azure.IoT Build 0:6ae2f7bca550 262
Azure.IoT Build 0:6ae2f7bca550 263 static void log_incoming_frame(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance, AMQP_VALUE performative)
Azure.IoT Build 0:6ae2f7bca550 264 {
Azure.IoT Build 0:6ae2f7bca550 265 if (sasl_client_io_instance->logger_log != NULL)
Azure.IoT Build 0:6ae2f7bca550 266 {
Azure.IoT Build 0:6ae2f7bca550 267 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
Azure.IoT Build 0:6ae2f7bca550 268 if (descriptor != NULL)
Azure.IoT Build 0:6ae2f7bca550 269 {
Azure.IoT Build 0:6ae2f7bca550 270 LOG(sasl_client_io_instance->logger_log, 0, "<- ");
Azure.IoT Build 0:6ae2f7bca550 271 LOG(sasl_client_io_instance->logger_log, 0, (char*)get_frame_type_as_string(descriptor));
Azure.IoT Build 0:6ae2f7bca550 272 char* performative_as_string = NULL;
Azure.IoT Build 0:6ae2f7bca550 273 LOG(sasl_client_io_instance->logger_log, LOG_LINE, (performative_as_string = amqpvalue_to_string(performative)));
Azure.IoT Build 0:6ae2f7bca550 274 if (performative_as_string != NULL)
Azure.IoT Build 0:6ae2f7bca550 275 {
Azure.IoT Build 0:6ae2f7bca550 276 amqpalloc_free(performative_as_string);
Azure.IoT Build 0:6ae2f7bca550 277 }
Azure.IoT Build 0:6ae2f7bca550 278 }
Azure.IoT Build 0:6ae2f7bca550 279 }
Azure.IoT Build 0:6ae2f7bca550 280 }
Azure.IoT Build 0:6ae2f7bca550 281
Azure.IoT Build 0:6ae2f7bca550 282 static void log_outgoing_frame(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance, AMQP_VALUE performative)
Azure.IoT Build 0:6ae2f7bca550 283 {
Azure.IoT Build 0:6ae2f7bca550 284 if (sasl_client_io_instance->logger_log != NULL)
Azure.IoT Build 0:6ae2f7bca550 285 {
Azure.IoT Build 0:6ae2f7bca550 286 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
Azure.IoT Build 0:6ae2f7bca550 287 if (descriptor != NULL)
Azure.IoT Build 0:6ae2f7bca550 288 {
Azure.IoT Build 0:6ae2f7bca550 289 LOG(sasl_client_io_instance->logger_log, 0, "-> ");
Azure.IoT Build 0:6ae2f7bca550 290 LOG(sasl_client_io_instance->logger_log, 0, (char*)get_frame_type_as_string(descriptor));
Azure.IoT Build 0:6ae2f7bca550 291 char* performative_as_string = NULL;
Azure.IoT Build 0:6ae2f7bca550 292 LOG(sasl_client_io_instance->logger_log, LOG_LINE, (performative_as_string = amqpvalue_to_string(performative)));
Azure.IoT Build 0:6ae2f7bca550 293 if (performative_as_string != NULL)
Azure.IoT Build 0:6ae2f7bca550 294 {
Azure.IoT Build 0:6ae2f7bca550 295 amqpalloc_free(performative_as_string);
Azure.IoT Build 0:6ae2f7bca550 296 }
Azure.IoT Build 0:6ae2f7bca550 297 }
Azure.IoT Build 0:6ae2f7bca550 298 }
Azure.IoT Build 0:6ae2f7bca550 299 }
Azure.IoT Build 0:6ae2f7bca550 300
Azure.IoT Build 0:6ae2f7bca550 301 static int saslclientio_receive_byte(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance, unsigned char b)
Azure.IoT Build 0:6ae2f7bca550 302 {
Azure.IoT Build 0:6ae2f7bca550 303 int result;
Azure.IoT Build 0:6ae2f7bca550 304
Azure.IoT Build 0:6ae2f7bca550 305 switch (sasl_client_io_instance->sasl_header_exchange_state)
Azure.IoT Build 0:6ae2f7bca550 306 {
Azure.IoT Build 0:6ae2f7bca550 307 default:
Azure.IoT Build 0:6ae2f7bca550 308 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 309 break;
Azure.IoT Build 0:6ae2f7bca550 310
Azure.IoT Build 0:6ae2f7bca550 311 case SASL_HEADER_EXCHANGE_HEADER_EXCH:
Azure.IoT Build 0:6ae2f7bca550 312 switch (sasl_client_io_instance->sasl_client_negotiation_state)
Azure.IoT Build 0:6ae2f7bca550 313 {
Azure.IoT Build 0:6ae2f7bca550 314 case SASL_CLIENT_NEGOTIATION_ERROR:
Azure.IoT Build 0:6ae2f7bca550 315 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 316 break;
Azure.IoT Build 0:6ae2f7bca550 317
Azure.IoT Build 0:6ae2f7bca550 318 default:
Azure.IoT Build 0:6ae2f7bca550 319 /* Codes_SRS_SASLCLIENTIO_01_068: [During the SASL frame exchange that constitutes the handshake the received bytes from the underlying IO shall be fed to the frame_codec instance created in saslclientio_create by calling frame_codec_receive_bytes.] */
Azure.IoT Build 0:6ae2f7bca550 320 if (frame_codec_receive_bytes(sasl_client_io_instance->frame_codec, &b, 1) != 0)
Azure.IoT Build 0:6ae2f7bca550 321 {
Azure.IoT Build 0:6ae2f7bca550 322 /* Codes_SRS_SASLCLIENTIO_01_088: [If frame_codec_receive_bytes fails, the state of SASL client IO shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 323 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 324 }
Azure.IoT Build 0:6ae2f7bca550 325 else
Azure.IoT Build 0:6ae2f7bca550 326 {
Azure.IoT Build 0:6ae2f7bca550 327 result = 0;
Azure.IoT Build 0:6ae2f7bca550 328 }
Azure.IoT Build 0:6ae2f7bca550 329
Azure.IoT Build 0:6ae2f7bca550 330 break;
Azure.IoT Build 0:6ae2f7bca550 331
Azure.IoT Build 0:6ae2f7bca550 332 case SASL_CLIENT_NEGOTIATION_OUTCOME_RCVD:
Azure.IoT Build 0:6ae2f7bca550 333 sasl_client_io_instance->on_bytes_received(sasl_client_io_instance->on_bytes_received_context, &b, 1);
Azure.IoT Build 0:6ae2f7bca550 334 result = 0;
Azure.IoT Build 0:6ae2f7bca550 335 break;
Azure.IoT Build 0:6ae2f7bca550 336 }
Azure.IoT Build 0:6ae2f7bca550 337
Azure.IoT Build 0:6ae2f7bca550 338 break;
Azure.IoT Build 0:6ae2f7bca550 339
Azure.IoT Build 0:6ae2f7bca550 340 /* Codes_SRS_SASLCLIENTIO_01_003: [Other than using a protocol id of three, the exchange of SASL layer headers follows the same rules specified in the version negotiation section of the transport specification (See Part 2: section 2.2).] */
Azure.IoT Build 0:6ae2f7bca550 341 case SASL_HEADER_EXCHANGE_IDLE:
Azure.IoT Build 0:6ae2f7bca550 342 case SASL_HEADER_EXCHANGE_HEADER_SENT:
Azure.IoT Build 0:6ae2f7bca550 343 if (b != sasl_header[sasl_client_io_instance->header_bytes_received])
Azure.IoT Build 0:6ae2f7bca550 344 {
Azure.IoT Build 0:6ae2f7bca550 345 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 346 }
Azure.IoT Build 0:6ae2f7bca550 347 else
Azure.IoT Build 0:6ae2f7bca550 348 {
Azure.IoT Build 0:6ae2f7bca550 349 sasl_client_io_instance->header_bytes_received++;
Azure.IoT Build 0:6ae2f7bca550 350 if (sasl_client_io_instance->header_bytes_received == sizeof(sasl_header))
Azure.IoT Build 0:6ae2f7bca550 351 {
Azure.IoT Build 0:6ae2f7bca550 352 LOG(sasl_client_io_instance->logger_log, LOG_LINE, "<- Header (AMQP 3.1.0.0)");
Azure.IoT Build 0:6ae2f7bca550 353
Azure.IoT Build 0:6ae2f7bca550 354 switch (sasl_client_io_instance->sasl_header_exchange_state)
Azure.IoT Build 0:6ae2f7bca550 355 {
Azure.IoT Build 0:6ae2f7bca550 356 default:
Azure.IoT Build 0:6ae2f7bca550 357 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 358 break;
Azure.IoT Build 0:6ae2f7bca550 359
Azure.IoT Build 0:6ae2f7bca550 360 case SASL_HEADER_EXCHANGE_HEADER_SENT:
Azure.IoT Build 0:6ae2f7bca550 361 /* from this point on we need to decode SASL frames */
Azure.IoT Build 0:6ae2f7bca550 362 sasl_client_io_instance->sasl_header_exchange_state = SASL_HEADER_EXCHANGE_HEADER_EXCH;
Azure.IoT Build 0:6ae2f7bca550 363 result = 0;
Azure.IoT Build 0:6ae2f7bca550 364 break;
Azure.IoT Build 0:6ae2f7bca550 365
Azure.IoT Build 0:6ae2f7bca550 366 case SASL_HEADER_EXCHANGE_IDLE:
Azure.IoT Build 0:6ae2f7bca550 367 sasl_client_io_instance->sasl_header_exchange_state = SASL_HEADER_EXCHANGE_HEADER_RCVD;
Azure.IoT Build 0:6ae2f7bca550 368 if (send_sasl_header(sasl_client_io_instance) != 0)
Azure.IoT Build 0:6ae2f7bca550 369 {
Azure.IoT Build 0:6ae2f7bca550 370 /* Codes_SRS_SASLCLIENTIO_01_077: [If sending the SASL header fails, the SASL client IO state shall be set to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 371 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 372 }
Azure.IoT Build 0:6ae2f7bca550 373 else
Azure.IoT Build 0:6ae2f7bca550 374 {
Azure.IoT Build 0:6ae2f7bca550 375 result = 0;
Azure.IoT Build 0:6ae2f7bca550 376 }
Azure.IoT Build 0:6ae2f7bca550 377
Azure.IoT Build 0:6ae2f7bca550 378 break;
Azure.IoT Build 0:6ae2f7bca550 379 }
Azure.IoT Build 0:6ae2f7bca550 380 }
Azure.IoT Build 0:6ae2f7bca550 381 else
Azure.IoT Build 0:6ae2f7bca550 382 {
Azure.IoT Build 0:6ae2f7bca550 383 result = 0;
Azure.IoT Build 0:6ae2f7bca550 384 }
Azure.IoT Build 0:6ae2f7bca550 385 }
Azure.IoT Build 0:6ae2f7bca550 386
Azure.IoT Build 0:6ae2f7bca550 387 break;
Azure.IoT Build 0:6ae2f7bca550 388 }
Azure.IoT Build 0:6ae2f7bca550 389
Azure.IoT Build 0:6ae2f7bca550 390 return result;
Azure.IoT Build 0:6ae2f7bca550 391 }
Azure.IoT Build 0:6ae2f7bca550 392
Azure.IoT Build 0:6ae2f7bca550 393 static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
Azure.IoT Build 0:6ae2f7bca550 394 {
Azure.IoT Build 0:6ae2f7bca550 395 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 396
Azure.IoT Build 0:6ae2f7bca550 397 /* Codes_SRS_SASLCLIENTIO_01_028: [If buffer is NULL or size is zero, nothing should be indicated as received and the saslio state shall be switched to ERROR the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 398 if ((buffer == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 399 (size == 0))
Azure.IoT Build 0:6ae2f7bca550 400 {
Azure.IoT Build 0:6ae2f7bca550 401 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 402 }
Azure.IoT Build 0:6ae2f7bca550 403 else
Azure.IoT Build 0:6ae2f7bca550 404 {
Azure.IoT Build 0:6ae2f7bca550 405 switch (sasl_client_io_instance->io_state)
Azure.IoT Build 0:6ae2f7bca550 406 {
Azure.IoT Build 0:6ae2f7bca550 407 default:
Azure.IoT Build 0:6ae2f7bca550 408 break;
Azure.IoT Build 0:6ae2f7bca550 409
Azure.IoT Build 0:6ae2f7bca550 410 case IO_STATE_OPEN:
Azure.IoT Build 0:6ae2f7bca550 411 /* Codes_SRS_SASLCLIENTIO_01_027: [When the on_bytes_received callback passed to the underlying IO is called and the SASL client IO state is IO_STATE_OPEN, the bytes shall be indicated to the user of SASL client IO by calling the on_bytes_received that was passed in saslclientio_open.] */
Azure.IoT Build 0:6ae2f7bca550 412 /* Codes_SRS_SASLCLIENTIO_01_029: [The context argument shall be set to the callback_context passed in saslclientio_open.] */
Azure.IoT Build 0:6ae2f7bca550 413 sasl_client_io_instance->on_bytes_received(sasl_client_io_instance->on_bytes_received_context, buffer, size);
Azure.IoT Build 0:6ae2f7bca550 414 break;
Azure.IoT Build 0:6ae2f7bca550 415
Azure.IoT Build 0:6ae2f7bca550 416 case IO_STATE_SASL_HANDSHAKE:
Azure.IoT Build 0:6ae2f7bca550 417 {
Azure.IoT Build 0:6ae2f7bca550 418 size_t i;
Azure.IoT Build 0:6ae2f7bca550 419
Azure.IoT Build 0:6ae2f7bca550 420 for (i = 0; i < size; i++)
Azure.IoT Build 0:6ae2f7bca550 421 {
Azure.IoT Build 0:6ae2f7bca550 422 if (saslclientio_receive_byte(sasl_client_io_instance, buffer[i]) != 0)
Azure.IoT Build 0:6ae2f7bca550 423 {
Azure.IoT Build 0:6ae2f7bca550 424 break;
Azure.IoT Build 0:6ae2f7bca550 425 }
Azure.IoT Build 0:6ae2f7bca550 426 }
Azure.IoT Build 0:6ae2f7bca550 427
Azure.IoT Build 0:6ae2f7bca550 428 if (i < size)
Azure.IoT Build 0:6ae2f7bca550 429 {
Azure.IoT Build 0:6ae2f7bca550 430 /* Codes_SRS_SASLCLIENTIO_01_073: [If the handshake fails (i.e. the outcome is an error) the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 431 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 432 }
Azure.IoT Build 0:6ae2f7bca550 433
Azure.IoT Build 0:6ae2f7bca550 434 break;
Azure.IoT Build 0:6ae2f7bca550 435 }
Azure.IoT Build 0:6ae2f7bca550 436
Azure.IoT Build 0:6ae2f7bca550 437 case IO_STATE_ERROR:
Azure.IoT Build 0:6ae2f7bca550 438 /* Codes_SRS_SASLCLIENTIO_01_031: [If bytes are received when the SASL client IO state is IO_STATE_ERROR, SASL client IO shall do nothing.] */
Azure.IoT Build 0:6ae2f7bca550 439 break;
Azure.IoT Build 0:6ae2f7bca550 440 }
Azure.IoT Build 0:6ae2f7bca550 441 }
Azure.IoT Build 0:6ae2f7bca550 442 }
Azure.IoT Build 0:6ae2f7bca550 443
Azure.IoT Build 0:6ae2f7bca550 444 static void on_bytes_encoded(void* context, const unsigned char* bytes, size_t length, bool encode_complete)
Azure.IoT Build 0:6ae2f7bca550 445 {
Azure.IoT Build 0:6ae2f7bca550 446 (void)encode_complete;
Azure.IoT Build 0:6ae2f7bca550 447
Azure.IoT Build 0:6ae2f7bca550 448 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 449
Azure.IoT Build 0:6ae2f7bca550 450 /* Codes_SRS_SASLCLIENTIO_01_120: [When SASL client IO is notified by sasl_frame_codec of bytes that have been encoded via the on_bytes_encoded callback and SASL client IO is in the state OPENING, SASL client IO shall send these bytes by using xio_send.] */
Azure.IoT Build 0:6ae2f7bca550 451 if (xio_send(sasl_client_io_instance->underlying_io, bytes, length, NULL, NULL) != 0)
Azure.IoT Build 0:6ae2f7bca550 452 {
Azure.IoT Build 0:6ae2f7bca550 453 /* Codes_SRS_SASLCLIENTIO_01_121: [If xio_send fails, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 454 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 455 }
Azure.IoT Build 0:6ae2f7bca550 456 }
Azure.IoT Build 0:6ae2f7bca550 457
Azure.IoT Build 0:6ae2f7bca550 458 static int send_sasl_init(SASL_CLIENT_IO_INSTANCE* sasl_client_io, const char* sasl_mechanism_name)
Azure.IoT Build 0:6ae2f7bca550 459 {
Azure.IoT Build 0:6ae2f7bca550 460 int result;
Azure.IoT Build 0:6ae2f7bca550 461
Azure.IoT Build 0:6ae2f7bca550 462 SASL_INIT_HANDLE sasl_init;
Azure.IoT Build 0:6ae2f7bca550 463 SASL_MECHANISM_BYTES init_bytes;
Azure.IoT Build 0:6ae2f7bca550 464
Azure.IoT Build 0:6ae2f7bca550 465 /* Codes_SRS_SASLCLIENTIO_01_045: [The name of the SASL mechanism used for the SASL exchange.] */
Azure.IoT Build 0:6ae2f7bca550 466 sasl_init = sasl_init_create(sasl_mechanism_name);
Azure.IoT Build 0:6ae2f7bca550 467 if (sasl_init == NULL)
Azure.IoT Build 0:6ae2f7bca550 468 {
Azure.IoT Build 0:6ae2f7bca550 469 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 470 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 471 }
Azure.IoT Build 0:6ae2f7bca550 472 else
Azure.IoT Build 0:6ae2f7bca550 473 {
Azure.IoT Build 0:6ae2f7bca550 474 /* Codes_SRS_SASLCLIENTIO_01_048: [The contents of this data are defined by the SASL security mechanism.] */
Azure.IoT Build 0:6ae2f7bca550 475 if (saslmechanism_get_init_bytes(sasl_client_io->sasl_mechanism, &init_bytes) != 0)
Azure.IoT Build 0:6ae2f7bca550 476 {
Azure.IoT Build 0:6ae2f7bca550 477 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 478 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 479 }
Azure.IoT Build 0:6ae2f7bca550 480 else
Azure.IoT Build 0:6ae2f7bca550 481 {
Azure.IoT Build 0:6ae2f7bca550 482 amqp_binary creds = { init_bytes.bytes, init_bytes.length };
Azure.IoT Build 0:6ae2f7bca550 483 if ((init_bytes.length > 0) &&
Azure.IoT Build 0:6ae2f7bca550 484 /* Codes_SRS_SASLCLIENTIO_01_047: [A block of opaque data passed to the security mechanism.] */
Azure.IoT Build 0:6ae2f7bca550 485 (sasl_init_set_initial_response(sasl_init, creds) != 0))
Azure.IoT Build 0:6ae2f7bca550 486 {
Azure.IoT Build 0:6ae2f7bca550 487 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 488 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 489 }
Azure.IoT Build 0:6ae2f7bca550 490 else
Azure.IoT Build 0:6ae2f7bca550 491 {
Azure.IoT Build 0:6ae2f7bca550 492 AMQP_VALUE sasl_init_value = amqpvalue_create_sasl_init(sasl_init);
Azure.IoT Build 0:6ae2f7bca550 493 if (sasl_init_value == NULL)
Azure.IoT Build 0:6ae2f7bca550 494 {
Azure.IoT Build 0:6ae2f7bca550 495 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 496 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 497 }
Azure.IoT Build 0:6ae2f7bca550 498 else
Azure.IoT Build 0:6ae2f7bca550 499 {
Azure.IoT Build 0:6ae2f7bca550 500 /* Codes_SRS_SASLCLIENTIO_01_070: [When a frame needs to be sent as part of the SASL handshake frame exchange, the send shall be done by calling sasl_frame_codec_encode_frame.] */
Azure.IoT Build 0:6ae2f7bca550 501 if (sasl_frame_codec_encode_frame(sasl_client_io->sasl_frame_codec, sasl_init_value, on_bytes_encoded, sasl_client_io) != 0)
Azure.IoT Build 0:6ae2f7bca550 502 {
Azure.IoT Build 0:6ae2f7bca550 503 /* Codes_SRS_SASLCLIENTIO_01_071: [If sasl_frame_codec_encode_frame fails, then the state of SASL client IO shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 504 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 505 }
Azure.IoT Build 0:6ae2f7bca550 506 else
Azure.IoT Build 0:6ae2f7bca550 507 {
Azure.IoT Build 0:6ae2f7bca550 508 log_outgoing_frame(sasl_client_io, sasl_init_value);
Azure.IoT Build 0:6ae2f7bca550 509
Azure.IoT Build 0:6ae2f7bca550 510 result = 0;
Azure.IoT Build 0:6ae2f7bca550 511 }
Azure.IoT Build 0:6ae2f7bca550 512
Azure.IoT Build 0:6ae2f7bca550 513 amqpvalue_destroy(sasl_init_value);
Azure.IoT Build 0:6ae2f7bca550 514 }
Azure.IoT Build 0:6ae2f7bca550 515 }
Azure.IoT Build 0:6ae2f7bca550 516 }
Azure.IoT Build 0:6ae2f7bca550 517
Azure.IoT Build 0:6ae2f7bca550 518 sasl_init_destroy(sasl_init);
Azure.IoT Build 0:6ae2f7bca550 519 }
Azure.IoT Build 0:6ae2f7bca550 520
Azure.IoT Build 0:6ae2f7bca550 521 return result;
Azure.IoT Build 0:6ae2f7bca550 522 }
Azure.IoT Build 0:6ae2f7bca550 523
Azure.IoT Build 0:6ae2f7bca550 524 static int send_sasl_response(SASL_CLIENT_IO_INSTANCE* sasl_client_io, SASL_MECHANISM_BYTES sasl_response)
Azure.IoT Build 0:6ae2f7bca550 525 {
Azure.IoT Build 0:6ae2f7bca550 526 int result;
Azure.IoT Build 0:6ae2f7bca550 527
Azure.IoT Build 0:6ae2f7bca550 528 SASL_RESPONSE_HANDLE sasl_response_handle;
Azure.IoT Build 0:6ae2f7bca550 529 amqp_binary response_binary_value = { sasl_response.bytes, sasl_response.length };
Azure.IoT Build 0:6ae2f7bca550 530
Azure.IoT Build 0:6ae2f7bca550 531 /* Codes_SRS_SASLCLIENTIO_01_055: [Send the SASL response data as defined by the SASL specification.] */
Azure.IoT Build 0:6ae2f7bca550 532 /* Codes_SRS_SASLCLIENTIO_01_056: [A block of opaque data passed to the security mechanism.] */
Azure.IoT Build 0:6ae2f7bca550 533 if ((sasl_response_handle = sasl_response_create(response_binary_value)) == NULL)
Azure.IoT Build 0:6ae2f7bca550 534 {
Azure.IoT Build 0:6ae2f7bca550 535 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 536 }
Azure.IoT Build 0:6ae2f7bca550 537 else
Azure.IoT Build 0:6ae2f7bca550 538 {
Azure.IoT Build 0:6ae2f7bca550 539 AMQP_VALUE sasl_response_value = amqpvalue_create_sasl_response(sasl_response_handle);
Azure.IoT Build 0:6ae2f7bca550 540 if (sasl_response_value == NULL)
Azure.IoT Build 0:6ae2f7bca550 541 {
Azure.IoT Build 0:6ae2f7bca550 542 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 543 }
Azure.IoT Build 0:6ae2f7bca550 544 else
Azure.IoT Build 0:6ae2f7bca550 545 {
Azure.IoT Build 0:6ae2f7bca550 546 /* Codes_SRS_SASLCLIENTIO_01_070: [When a frame needs to be sent as part of the SASL handshake frame exchange, the send shall be done by calling sasl_frame_codec_encode_frame.] */
Azure.IoT Build 0:6ae2f7bca550 547 if (sasl_frame_codec_encode_frame(sasl_client_io->sasl_frame_codec, sasl_response_value, on_bytes_encoded, sasl_client_io) != 0)
Azure.IoT Build 0:6ae2f7bca550 548 {
Azure.IoT Build 0:6ae2f7bca550 549 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 550 }
Azure.IoT Build 0:6ae2f7bca550 551 else
Azure.IoT Build 0:6ae2f7bca550 552 {
Azure.IoT Build 0:6ae2f7bca550 553 log_outgoing_frame(sasl_client_io, sasl_response_value);
Azure.IoT Build 0:6ae2f7bca550 554
Azure.IoT Build 0:6ae2f7bca550 555 result = 0;
Azure.IoT Build 0:6ae2f7bca550 556 }
Azure.IoT Build 0:6ae2f7bca550 557
Azure.IoT Build 0:6ae2f7bca550 558 amqpvalue_destroy(sasl_response_value);
Azure.IoT Build 0:6ae2f7bca550 559 }
Azure.IoT Build 0:6ae2f7bca550 560
Azure.IoT Build 0:6ae2f7bca550 561 sasl_response_destroy(sasl_response_handle);
Azure.IoT Build 0:6ae2f7bca550 562 }
Azure.IoT Build 0:6ae2f7bca550 563
Azure.IoT Build 0:6ae2f7bca550 564 return result;
Azure.IoT Build 0:6ae2f7bca550 565 }
Azure.IoT Build 0:6ae2f7bca550 566
Azure.IoT Build 0:6ae2f7bca550 567 static void sasl_frame_received_callback(void* context, AMQP_VALUE sasl_frame)
Azure.IoT Build 0:6ae2f7bca550 568 {
Azure.IoT Build 0:6ae2f7bca550 569 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 570
Azure.IoT Build 0:6ae2f7bca550 571 /* Codes_SRS_SASLCLIENTIO_01_067: [The SASL frame exchange shall be started as soon as the SASL header handshake is done.] */
Azure.IoT Build 0:6ae2f7bca550 572 switch (sasl_client_io_instance->io_state)
Azure.IoT Build 0:6ae2f7bca550 573 {
Azure.IoT Build 0:6ae2f7bca550 574 default:
Azure.IoT Build 0:6ae2f7bca550 575 break;
Azure.IoT Build 0:6ae2f7bca550 576
Azure.IoT Build 0:6ae2f7bca550 577 case IO_STATE_OPEN:
Azure.IoT Build 0:6ae2f7bca550 578 case IO_STATE_OPENING_UNDERLYING_IO:
Azure.IoT Build 0:6ae2f7bca550 579 case IO_STATE_CLOSING:
Azure.IoT Build 0:6ae2f7bca550 580 /* Codes_SRS_SASLCLIENTIO_01_117: [If on_sasl_frame_received_callback is called when the state of the IO is OPEN then the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 581 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 582 break;
Azure.IoT Build 0:6ae2f7bca550 583
Azure.IoT Build 0:6ae2f7bca550 584 case IO_STATE_SASL_HANDSHAKE:
Azure.IoT Build 0:6ae2f7bca550 585 if (sasl_client_io_instance->sasl_header_exchange_state != SASL_HEADER_EXCHANGE_HEADER_EXCH)
Azure.IoT Build 0:6ae2f7bca550 586 {
Azure.IoT Build 0:6ae2f7bca550 587 /* Codes_SRS_SASLCLIENTIO_01_118: [If on_sasl_frame_received_callback is called in the OPENING state but the header exchange has not yet been completed, then the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 588 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 589 }
Azure.IoT Build 0:6ae2f7bca550 590 else
Azure.IoT Build 0:6ae2f7bca550 591 {
Azure.IoT Build 0:6ae2f7bca550 592 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(sasl_frame);
Azure.IoT Build 0:6ae2f7bca550 593 if (descriptor == NULL)
Azure.IoT Build 0:6ae2f7bca550 594 {
Azure.IoT Build 0:6ae2f7bca550 595 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 596 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 597 }
Azure.IoT Build 0:6ae2f7bca550 598 else
Azure.IoT Build 0:6ae2f7bca550 599 {
Azure.IoT Build 0:6ae2f7bca550 600 log_incoming_frame(sasl_client_io_instance, sasl_frame);
Azure.IoT Build 0:6ae2f7bca550 601
Azure.IoT Build 0:6ae2f7bca550 602 /* Codes_SRS_SASLCLIENTIO_01_032: [The peer acting as the SASL server MUST announce supported authentication mechanisms using the sasl-mechanisms frame.] */
Azure.IoT Build 0:6ae2f7bca550 603 /* Codes_SRS_SASLCLIENTIO_01_040: [The peer playing the role of the SASL client and the peer playing the role of the SASL server MUST correspond to the TCP client and server respectively.] */
Azure.IoT Build 0:6ae2f7bca550 604 /* Codes_SRS_SASLCLIENTIO_01_034: [<-- SASL-MECHANISMS] */
Azure.IoT Build 0:6ae2f7bca550 605 if (is_sasl_mechanisms_type_by_descriptor(descriptor))
Azure.IoT Build 0:6ae2f7bca550 606 {
Azure.IoT Build 0:6ae2f7bca550 607 switch (sasl_client_io_instance->sasl_client_negotiation_state)
Azure.IoT Build 0:6ae2f7bca550 608 {
Azure.IoT Build 0:6ae2f7bca550 609 case SASL_CLIENT_NEGOTIATION_NOT_STARTED:
Azure.IoT Build 0:6ae2f7bca550 610 {
Azure.IoT Build 0:6ae2f7bca550 611 SASL_MECHANISMS_HANDLE sasl_mechanisms_handle;
Azure.IoT Build 0:6ae2f7bca550 612
Azure.IoT Build 0:6ae2f7bca550 613 if (amqpvalue_get_sasl_mechanisms(sasl_frame, &sasl_mechanisms_handle) != 0)
Azure.IoT Build 0:6ae2f7bca550 614 {
Azure.IoT Build 0:6ae2f7bca550 615 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 616 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 617 }
Azure.IoT Build 0:6ae2f7bca550 618 else
Azure.IoT Build 0:6ae2f7bca550 619 {
Azure.IoT Build 0:6ae2f7bca550 620 AMQP_VALUE sasl_server_mechanisms;
Azure.IoT Build 0:6ae2f7bca550 621 uint32_t mechanisms_count;
Azure.IoT Build 0:6ae2f7bca550 622
Azure.IoT Build 0:6ae2f7bca550 623 if ((sasl_mechanisms_get_sasl_server_mechanisms(sasl_mechanisms_handle, &sasl_server_mechanisms) != 0) ||
Azure.IoT Build 0:6ae2f7bca550 624 (amqpvalue_get_array_item_count(sasl_server_mechanisms, &mechanisms_count) != 0) ||
Azure.IoT Build 0:6ae2f7bca550 625 (mechanisms_count == 0))
Azure.IoT Build 0:6ae2f7bca550 626 {
Azure.IoT Build 0:6ae2f7bca550 627 /* Codes_SRS_SASLCLIENTIO_01_042: [It is invalid for this list to be null or empty.] */
Azure.IoT Build 0:6ae2f7bca550 628 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 629 }
Azure.IoT Build 0:6ae2f7bca550 630 else
Azure.IoT Build 0:6ae2f7bca550 631 {
Azure.IoT Build 0:6ae2f7bca550 632 const char* sasl_mechanism_name = saslmechanism_get_mechanism_name(sasl_client_io_instance->sasl_mechanism);
Azure.IoT Build 0:6ae2f7bca550 633 if (sasl_mechanism_name == NULL)
Azure.IoT Build 0:6ae2f7bca550 634 {
Azure.IoT Build 0:6ae2f7bca550 635 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 636 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 637 }
Azure.IoT Build 0:6ae2f7bca550 638 else
Azure.IoT Build 0:6ae2f7bca550 639 {
Azure.IoT Build 0:6ae2f7bca550 640 uint32_t i;
Azure.IoT Build 0:6ae2f7bca550 641
Azure.IoT Build 0:6ae2f7bca550 642 for (i = 0; i < mechanisms_count; i++)
Azure.IoT Build 0:6ae2f7bca550 643 {
Azure.IoT Build 0:6ae2f7bca550 644 AMQP_VALUE sasl_server_mechanism;
Azure.IoT Build 0:6ae2f7bca550 645 sasl_server_mechanism = amqpvalue_get_array_item(sasl_server_mechanisms, i);
Azure.IoT Build 0:6ae2f7bca550 646 if (sasl_server_mechanism == NULL)
Azure.IoT Build 0:6ae2f7bca550 647 {
Azure.IoT Build 0:6ae2f7bca550 648 i = mechanisms_count;
Azure.IoT Build 0:6ae2f7bca550 649 }
Azure.IoT Build 0:6ae2f7bca550 650 else
Azure.IoT Build 0:6ae2f7bca550 651 {
Azure.IoT Build 0:6ae2f7bca550 652 const char* sasl_server_mechanism_name;
Azure.IoT Build 0:6ae2f7bca550 653 if (amqpvalue_get_symbol(sasl_server_mechanism, &sasl_server_mechanism_name) != 0)
Azure.IoT Build 0:6ae2f7bca550 654 {
Azure.IoT Build 0:6ae2f7bca550 655 i = mechanisms_count;
Azure.IoT Build 0:6ae2f7bca550 656 }
Azure.IoT Build 0:6ae2f7bca550 657 else
Azure.IoT Build 0:6ae2f7bca550 658 {
Azure.IoT Build 0:6ae2f7bca550 659 if (strcmp(sasl_mechanism_name, sasl_server_mechanism_name) == 0)
Azure.IoT Build 0:6ae2f7bca550 660 {
Azure.IoT Build 0:6ae2f7bca550 661 amqpvalue_destroy(sasl_server_mechanism);
Azure.IoT Build 0:6ae2f7bca550 662 break;
Azure.IoT Build 0:6ae2f7bca550 663 }
Azure.IoT Build 0:6ae2f7bca550 664 }
Azure.IoT Build 0:6ae2f7bca550 665
Azure.IoT Build 0:6ae2f7bca550 666 amqpvalue_destroy(sasl_server_mechanism);
Azure.IoT Build 0:6ae2f7bca550 667 }
Azure.IoT Build 0:6ae2f7bca550 668 }
Azure.IoT Build 0:6ae2f7bca550 669
Azure.IoT Build 0:6ae2f7bca550 670 if (i == mechanisms_count)
Azure.IoT Build 0:6ae2f7bca550 671 {
Azure.IoT Build 0:6ae2f7bca550 672 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 673 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 674 }
Azure.IoT Build 0:6ae2f7bca550 675 else
Azure.IoT Build 0:6ae2f7bca550 676 {
Azure.IoT Build 0:6ae2f7bca550 677 sasl_client_io_instance->sasl_client_negotiation_state = SASL_CLIENT_NEGOTIATION_MECH_RCVD;
Azure.IoT Build 0:6ae2f7bca550 678
Azure.IoT Build 0:6ae2f7bca550 679 /* Codes_SRS_SASLCLIENTIO_01_035: [SASL-INIT -->] */
Azure.IoT Build 0:6ae2f7bca550 680 /* Codes_SRS_SASLCLIENTIO_01_033: [The partner MUST then choose one of the supported mechanisms and initiate a sasl exchange.] */
Azure.IoT Build 0:6ae2f7bca550 681 /* Codes_SRS_SASLCLIENTIO_01_054: [Selects the sasl mechanism and provides the initial response if needed.] */
Azure.IoT Build 0:6ae2f7bca550 682 if (send_sasl_init(sasl_client_io_instance, sasl_mechanism_name) != 0)
Azure.IoT Build 0:6ae2f7bca550 683 {
Azure.IoT Build 0:6ae2f7bca550 684 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 685 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 686 }
Azure.IoT Build 0:6ae2f7bca550 687 else
Azure.IoT Build 0:6ae2f7bca550 688 {
Azure.IoT Build 0:6ae2f7bca550 689 sasl_client_io_instance->sasl_client_negotiation_state = SASL_CLIENT_NEGOTIATION_INIT_SENT;
Azure.IoT Build 0:6ae2f7bca550 690 }
Azure.IoT Build 0:6ae2f7bca550 691 }
Azure.IoT Build 0:6ae2f7bca550 692 }
Azure.IoT Build 0:6ae2f7bca550 693 }
Azure.IoT Build 0:6ae2f7bca550 694
Azure.IoT Build 0:6ae2f7bca550 695 sasl_mechanisms_destroy(sasl_mechanisms_handle);
Azure.IoT Build 0:6ae2f7bca550 696 }
Azure.IoT Build 0:6ae2f7bca550 697
Azure.IoT Build 0:6ae2f7bca550 698 break;
Azure.IoT Build 0:6ae2f7bca550 699 }
Azure.IoT Build 0:6ae2f7bca550 700 }
Azure.IoT Build 0:6ae2f7bca550 701 }
Azure.IoT Build 0:6ae2f7bca550 702 /* Codes_SRS_SASLCLIENTIO_01_052: [Send the SASL challenge data as defined by the SASL specification.] */
Azure.IoT Build 0:6ae2f7bca550 703 /* Codes_SRS_SASLCLIENTIO_01_036: [<-- SASL-CHALLENGE *] */
Azure.IoT Build 0:6ae2f7bca550 704 /* Codes_SRS_SASLCLIENTIO_01_039: [the SASL challenge/response step can occur zero or more times depending on the details of the SASL mechanism chosen.] */
Azure.IoT Build 0:6ae2f7bca550 705 else if (is_sasl_challenge_type_by_descriptor(descriptor))
Azure.IoT Build 0:6ae2f7bca550 706 {
Azure.IoT Build 0:6ae2f7bca550 707 /* Codes_SRS_SASLCLIENTIO_01_032: [The peer acting as the SASL server MUST announce supported authentication mechanisms using the sasl-mechanisms frame.] */
Azure.IoT Build 0:6ae2f7bca550 708 if ((sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_INIT_SENT) &&
Azure.IoT Build 0:6ae2f7bca550 709 (sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_RESPONSE_SENT))
Azure.IoT Build 0:6ae2f7bca550 710 {
Azure.IoT Build 0:6ae2f7bca550 711 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 712 }
Azure.IoT Build 0:6ae2f7bca550 713 else
Azure.IoT Build 0:6ae2f7bca550 714 {
Azure.IoT Build 0:6ae2f7bca550 715 SASL_CHALLENGE_HANDLE sasl_challenge_handle;
Azure.IoT Build 0:6ae2f7bca550 716
Azure.IoT Build 0:6ae2f7bca550 717 if (amqpvalue_get_sasl_challenge(sasl_frame, &sasl_challenge_handle) != 0)
Azure.IoT Build 0:6ae2f7bca550 718 {
Azure.IoT Build 0:6ae2f7bca550 719 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 720 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 721 }
Azure.IoT Build 0:6ae2f7bca550 722 else
Azure.IoT Build 0:6ae2f7bca550 723 {
Azure.IoT Build 0:6ae2f7bca550 724 amqp_binary challenge_binary_value;
Azure.IoT Build 0:6ae2f7bca550 725 SASL_MECHANISM_BYTES response_bytes;
Azure.IoT Build 0:6ae2f7bca550 726
Azure.IoT Build 0:6ae2f7bca550 727 /* Codes_SRS_SASLCLIENTIO_01_053: [Challenge information, a block of opaque binary data passed to the security mechanism.] */
Azure.IoT Build 0:6ae2f7bca550 728 if (sasl_challenge_get_challenge(sasl_challenge_handle, &challenge_binary_value) != 0)
Azure.IoT Build 0:6ae2f7bca550 729 {
Azure.IoT Build 0:6ae2f7bca550 730 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 731 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 732 }
Azure.IoT Build 0:6ae2f7bca550 733 else
Azure.IoT Build 0:6ae2f7bca550 734 {
Azure.IoT Build 0:6ae2f7bca550 735 SASL_MECHANISM_BYTES challenge = { challenge_binary_value.bytes, challenge_binary_value.length };
Azure.IoT Build 0:6ae2f7bca550 736
Azure.IoT Build 0:6ae2f7bca550 737 /* Codes_SRS_SASLCLIENTIO_01_057: [The contents of this data are defined by the SASL security mechanism.] */
Azure.IoT Build 0:6ae2f7bca550 738 /* Codes_SRS_SASLCLIENTIO_01_037: [SASL-RESPONSE -->] */
Azure.IoT Build 0:6ae2f7bca550 739 if ((saslmechanism_challenge(sasl_client_io_instance->sasl_mechanism, &challenge, &response_bytes) != 0) ||
Azure.IoT Build 0:6ae2f7bca550 740 (send_sasl_response(sasl_client_io_instance, response_bytes) != 0))
Azure.IoT Build 0:6ae2f7bca550 741 {
Azure.IoT Build 0:6ae2f7bca550 742 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 743 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 744 }
Azure.IoT Build 0:6ae2f7bca550 745 }
Azure.IoT Build 0:6ae2f7bca550 746
Azure.IoT Build 0:6ae2f7bca550 747 sasl_challenge_destroy(sasl_challenge_handle);
Azure.IoT Build 0:6ae2f7bca550 748 }
Azure.IoT Build 0:6ae2f7bca550 749 }
Azure.IoT Build 0:6ae2f7bca550 750 }
Azure.IoT Build 0:6ae2f7bca550 751 /* Codes_SRS_SASLCLIENTIO_01_058: [This frame indicates the outcome of the SASL dialog.] */
Azure.IoT Build 0:6ae2f7bca550 752 /* Codes_SRS_SASLCLIENTIO_01_038: [<-- SASL-OUTCOME] */
Azure.IoT Build 0:6ae2f7bca550 753 else if (is_sasl_outcome_type_by_descriptor(descriptor))
Azure.IoT Build 0:6ae2f7bca550 754 {
Azure.IoT Build 0:6ae2f7bca550 755 /* Codes_SRS_SASLCLIENTIO_01_032: [The peer acting as the SASL server MUST announce supported authentication mechanisms using the sasl-mechanisms frame.] */
Azure.IoT Build 0:6ae2f7bca550 756 if ((sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_INIT_SENT) &&
Azure.IoT Build 0:6ae2f7bca550 757 (sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_RESPONSE_SENT))
Azure.IoT Build 0:6ae2f7bca550 758 {
Azure.IoT Build 0:6ae2f7bca550 759 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 760 }
Azure.IoT Build 0:6ae2f7bca550 761 else
Azure.IoT Build 0:6ae2f7bca550 762 {
Azure.IoT Build 0:6ae2f7bca550 763 SASL_OUTCOME_HANDLE sasl_outcome;
Azure.IoT Build 0:6ae2f7bca550 764
Azure.IoT Build 0:6ae2f7bca550 765 sasl_client_io_instance->sasl_client_negotiation_state = SASL_CLIENT_NEGOTIATION_OUTCOME_RCVD;
Azure.IoT Build 0:6ae2f7bca550 766
Azure.IoT Build 0:6ae2f7bca550 767 if (amqpvalue_get_sasl_outcome(sasl_frame, &sasl_outcome) != 0)
Azure.IoT Build 0:6ae2f7bca550 768 {
Azure.IoT Build 0:6ae2f7bca550 769 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 770 }
Azure.IoT Build 0:6ae2f7bca550 771 else
Azure.IoT Build 0:6ae2f7bca550 772 {
Azure.IoT Build 0:6ae2f7bca550 773 sasl_code sasl_code;
Azure.IoT Build 0:6ae2f7bca550 774
Azure.IoT Build 0:6ae2f7bca550 775 /* Codes_SRS_SASLCLIENTIO_01_060: [A reply-code indicating the outcome of the SASL dialog.] */
Azure.IoT Build 0:6ae2f7bca550 776 if (sasl_outcome_get_code(sasl_outcome, &sasl_code) != 0)
Azure.IoT Build 0:6ae2f7bca550 777 {
Azure.IoT Build 0:6ae2f7bca550 778 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 779 }
Azure.IoT Build 0:6ae2f7bca550 780 else
Azure.IoT Build 0:6ae2f7bca550 781 {
Azure.IoT Build 0:6ae2f7bca550 782 switch (sasl_code)
Azure.IoT Build 0:6ae2f7bca550 783 {
Azure.IoT Build 0:6ae2f7bca550 784 default:
Azure.IoT Build 0:6ae2f7bca550 785 case sasl_code_auth:
Azure.IoT Build 0:6ae2f7bca550 786 /* Codes_SRS_SASLCLIENTIO_01_063: [1 Connection authentication failed due to an unspecified problem with the supplied credentials.] */
Azure.IoT Build 0:6ae2f7bca550 787 case sasl_code_sys:
Azure.IoT Build 0:6ae2f7bca550 788 /* Codes_SRS_SASLCLIENTIO_01_064: [2 Connection authentication failed due to a system error.] */
Azure.IoT Build 0:6ae2f7bca550 789 case sasl_code_sys_perm:
Azure.IoT Build 0:6ae2f7bca550 790 /* Codes_SRS_SASLCLIENTIO_01_065: [3 Connection authentication failed due to a system error that is unlikely to be corrected without intervention.] */
Azure.IoT Build 0:6ae2f7bca550 791 case sasl_code_sys_temp:
Azure.IoT Build 0:6ae2f7bca550 792 /* Codes_SRS_SASLCLIENTIO_01_066: [4 Connection authentication failed due to a transient system error.] */
Azure.IoT Build 0:6ae2f7bca550 793 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 794 break;
Azure.IoT Build 0:6ae2f7bca550 795
Azure.IoT Build 0:6ae2f7bca550 796 case sasl_code_ok:
Azure.IoT Build 0:6ae2f7bca550 797 /* Codes_SRS_SASLCLIENTIO_01_059: [Upon successful completion of the SASL dialog the security layer has been established] */
Azure.IoT Build 0:6ae2f7bca550 798 /* Codes_SRS_SASLCLIENTIO_01_062: [0 Connection authentication succeeded.] */
Azure.IoT Build 0:6ae2f7bca550 799 sasl_client_io_instance->io_state = IO_STATE_OPEN;
Azure.IoT Build 0:6ae2f7bca550 800 indicate_open_complete(sasl_client_io_instance, IO_OPEN_OK);
Azure.IoT Build 0:6ae2f7bca550 801 break;
Azure.IoT Build 0:6ae2f7bca550 802 }
Azure.IoT Build 0:6ae2f7bca550 803 }
Azure.IoT Build 0:6ae2f7bca550 804
Azure.IoT Build 0:6ae2f7bca550 805 sasl_outcome_destroy(sasl_outcome);
Azure.IoT Build 0:6ae2f7bca550 806 }
Azure.IoT Build 0:6ae2f7bca550 807 }
Azure.IoT Build 0:6ae2f7bca550 808 }
Azure.IoT Build 0:6ae2f7bca550 809 else
Azure.IoT Build 0:6ae2f7bca550 810 {
Azure.IoT Build 0:6ae2f7bca550 811 LOG(sasl_client_io_instance->logger_log, LOG_LINE, "Bad SASL frame");
Azure.IoT Build 0:6ae2f7bca550 812 }
Azure.IoT Build 0:6ae2f7bca550 813 }
Azure.IoT Build 0:6ae2f7bca550 814 }
Azure.IoT Build 0:6ae2f7bca550 815 break;
Azure.IoT Build 0:6ae2f7bca550 816 }
Azure.IoT Build 0:6ae2f7bca550 817 }
Azure.IoT Build 0:6ae2f7bca550 818
Azure.IoT Build 0:6ae2f7bca550 819 static void on_frame_codec_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 820 {
Azure.IoT Build 0:6ae2f7bca550 821 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 822
Azure.IoT Build 0:6ae2f7bca550 823 /* Codes_SRS_SASLCLIENTIO_01_122: [When on_frame_codec_error is called while in the OPENING or OPEN state the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 824 /* Codes_SRS_SASLCLIENTIO_01_123: [When on_frame_codec_error is called in the ERROR state nothing shall be done.] */
Azure.IoT Build 0:6ae2f7bca550 825 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 826 }
Azure.IoT Build 0:6ae2f7bca550 827
Azure.IoT Build 0:6ae2f7bca550 828 static void on_sasl_frame_codec_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 829 {
Azure.IoT Build 0:6ae2f7bca550 830 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 831
Azure.IoT Build 0:6ae2f7bca550 832 /* Codes_SRS_SASLCLIENTIO_01_124: [**When on_sasl_frame_codec_error is called while in the OPENING or OPEN state the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */
Azure.IoT Build 0:6ae2f7bca550 833 /* Codes_SRS_SASLCLIENTIO_01_125: [When on_sasl_frame_codec_error is called in the ERROR state nothing shall be done.] */
Azure.IoT Build 0:6ae2f7bca550 834 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 835 }
Azure.IoT Build 0:6ae2f7bca550 836
Azure.IoT Build 0:6ae2f7bca550 837 CONCRETE_IO_HANDLE saslclientio_create(void* io_create_parameters, LOGGER_LOG logger_log)
Azure.IoT Build 0:6ae2f7bca550 838 {
Azure.IoT Build 0:6ae2f7bca550 839 SASLCLIENTIO_CONFIG* sasl_client_io_config = io_create_parameters;
Azure.IoT Build 0:6ae2f7bca550 840 SASL_CLIENT_IO_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 841
Azure.IoT Build 0:6ae2f7bca550 842 /* Codes_SRS_SASLCLIENTIO_01_005: [If xio_create_parameters is NULL, saslclientio_create shall fail and return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 843 if ((sasl_client_io_config == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 844 /* Codes_SRS_SASLCLIENTIO_01_092: [If any of the sasl_mechanism or underlying_io members of the configuration structure are NULL, saslclientio_create shall fail and return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 845 (sasl_client_io_config->underlying_io == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 846 (sasl_client_io_config->sasl_mechanism == NULL))
Azure.IoT Build 0:6ae2f7bca550 847 {
Azure.IoT Build 0:6ae2f7bca550 848 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 849 }
Azure.IoT Build 0:6ae2f7bca550 850 else
Azure.IoT Build 0:6ae2f7bca550 851 {
Azure.IoT Build 0:6ae2f7bca550 852 result = amqpalloc_malloc(sizeof(SASL_CLIENT_IO_INSTANCE));
Azure.IoT Build 0:6ae2f7bca550 853 /* Codes_SRS_SASLCLIENTIO_01_006: [If memory cannot be allocated for the new instance, saslclientio_create shall fail and return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 854 if (result != NULL)
Azure.IoT Build 0:6ae2f7bca550 855 {
Azure.IoT Build 0:6ae2f7bca550 856 result->underlying_io = sasl_client_io_config->underlying_io;
Azure.IoT Build 0:6ae2f7bca550 857 if (result->underlying_io == NULL)
Azure.IoT Build 0:6ae2f7bca550 858 {
Azure.IoT Build 0:6ae2f7bca550 859 amqpalloc_free(result);
Azure.IoT Build 0:6ae2f7bca550 860 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 861 }
Azure.IoT Build 0:6ae2f7bca550 862 else
Azure.IoT Build 0:6ae2f7bca550 863 {
Azure.IoT Build 0:6ae2f7bca550 864 /* Codes_SRS_SASLCLIENTIO_01_089: [saslclientio_create shall create a frame_codec to be used for encoding/decoding frames bycalling frame_codec_create and passing the underlying_io as argument.] */
Azure.IoT Build 0:6ae2f7bca550 865 result->frame_codec = frame_codec_create(on_frame_codec_error, result, logger_log);
Azure.IoT Build 0:6ae2f7bca550 866 if (result->frame_codec == NULL)
Azure.IoT Build 0:6ae2f7bca550 867 {
Azure.IoT Build 0:6ae2f7bca550 868 /* Codes_SRS_SASLCLIENTIO_01_090: [If frame_codec_create fails, then saslclientio_create shall fail and return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 869 amqpalloc_free(result);
Azure.IoT Build 0:6ae2f7bca550 870 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 871 }
Azure.IoT Build 0:6ae2f7bca550 872 else
Azure.IoT Build 0:6ae2f7bca550 873 {
Azure.IoT Build 0:6ae2f7bca550 874 /* Codes_SRS_SASLCLIENTIO_01_084: [saslclientio_create shall create a sasl_frame_codec to be used for SASL frame encoding/decoding by calling sasl_frame_codec_create and passing the just created frame_codec as argument.] */
Azure.IoT Build 0:6ae2f7bca550 875 result->sasl_frame_codec = sasl_frame_codec_create(result->frame_codec, sasl_frame_received_callback, on_sasl_frame_codec_error, result);
Azure.IoT Build 0:6ae2f7bca550 876 if (result->sasl_frame_codec == NULL)
Azure.IoT Build 0:6ae2f7bca550 877 {
Azure.IoT Build 0:6ae2f7bca550 878 frame_codec_destroy(result->frame_codec);
Azure.IoT Build 0:6ae2f7bca550 879 amqpalloc_free(result);
Azure.IoT Build 0:6ae2f7bca550 880 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 881 }
Azure.IoT Build 0:6ae2f7bca550 882 else
Azure.IoT Build 0:6ae2f7bca550 883 {
Azure.IoT Build 0:6ae2f7bca550 884 /* Codes_SRS_SASLCLIENTIO_01_004: [saslclientio_create shall return on success a non-NULL handle to a new SASL client IO instance.] */
Azure.IoT Build 0:6ae2f7bca550 885 result->on_bytes_received = NULL;
Azure.IoT Build 0:6ae2f7bca550 886 result->on_io_open_complete = NULL;
Azure.IoT Build 0:6ae2f7bca550 887 result->on_io_error = NULL;
Azure.IoT Build 0:6ae2f7bca550 888 result->on_io_close_complete = NULL;
Azure.IoT Build 0:6ae2f7bca550 889 result->logger_log = logger_log;
Azure.IoT Build 0:6ae2f7bca550 890 result->on_bytes_received_context = NULL;
Azure.IoT Build 0:6ae2f7bca550 891 result->on_io_open_complete_context = NULL;
Azure.IoT Build 0:6ae2f7bca550 892 result->on_io_close_complete_context = NULL;
Azure.IoT Build 0:6ae2f7bca550 893 result->on_io_error_context = NULL;
Azure.IoT Build 0:6ae2f7bca550 894 result->sasl_mechanism = sasl_client_io_config->sasl_mechanism;
Azure.IoT Build 0:6ae2f7bca550 895
Azure.IoT Build 0:6ae2f7bca550 896 result->io_state = IO_STATE_NOT_OPEN;
Azure.IoT Build 0:6ae2f7bca550 897 }
Azure.IoT Build 0:6ae2f7bca550 898 }
Azure.IoT Build 0:6ae2f7bca550 899 }
Azure.IoT Build 0:6ae2f7bca550 900 }
Azure.IoT Build 0:6ae2f7bca550 901 }
Azure.IoT Build 0:6ae2f7bca550 902
Azure.IoT Build 0:6ae2f7bca550 903 return result;
Azure.IoT Build 0:6ae2f7bca550 904 }
Azure.IoT Build 0:6ae2f7bca550 905
Azure.IoT Build 0:6ae2f7bca550 906 void saslclientio_destroy(CONCRETE_IO_HANDLE sasl_client_io)
Azure.IoT Build 0:6ae2f7bca550 907 {
Azure.IoT Build 0:6ae2f7bca550 908 if (sasl_client_io != NULL)
Azure.IoT Build 0:6ae2f7bca550 909 {
Azure.IoT Build 0:6ae2f7bca550 910 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
Azure.IoT Build 0:6ae2f7bca550 911
Azure.IoT Build 0:6ae2f7bca550 912 /* Codes_SRS_SASLCLIENTIO_01_007: [saslclientio_destroy shall free all resources associated with the SASL client IO handle.] */
Azure.IoT Build 0:6ae2f7bca550 913 /* Codes_SRS_SASLCLIENTIO_01_086: [saslclientio_destroy shall destroy the sasl_frame_codec created in saslclientio_create by calling sasl_frame_codec_destroy.] */
Azure.IoT Build 0:6ae2f7bca550 914 sasl_frame_codec_destroy(sasl_client_io_instance->sasl_frame_codec);
Azure.IoT Build 0:6ae2f7bca550 915
Azure.IoT Build 0:6ae2f7bca550 916 /* Codes_SRS_SASLCLIENTIO_01_091: [saslclientio_destroy shall destroy the frame_codec created in saslclientio_create by calling frame_codec_destroy.] */
Azure.IoT Build 0:6ae2f7bca550 917 frame_codec_destroy(sasl_client_io_instance->frame_codec);
Azure.IoT Build 0:6ae2f7bca550 918 amqpalloc_free(sasl_client_io);
Azure.IoT Build 0:6ae2f7bca550 919 }
Azure.IoT Build 0:6ae2f7bca550 920 }
Azure.IoT Build 0:6ae2f7bca550 921
Azure.IoT Build 0:6ae2f7bca550 922 int saslclientio_open(CONCRETE_IO_HANDLE sasl_client_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
Azure.IoT Build 0:6ae2f7bca550 923 {
Azure.IoT Build 0:6ae2f7bca550 924 int result = 0;
Azure.IoT Build 0:6ae2f7bca550 925
Azure.IoT Build 0:6ae2f7bca550 926 /* Codes_SRS_SASLCLIENTIO_01_011: [If any of the sasl_client_io or on_bytes_received arguments is NULL, saslclientio_open shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 927 if ((sasl_client_io == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 928 (on_bytes_received == NULL))
Azure.IoT Build 0:6ae2f7bca550 929 {
Azure.IoT Build 0:6ae2f7bca550 930 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 931 }
Azure.IoT Build 0:6ae2f7bca550 932 else
Azure.IoT Build 0:6ae2f7bca550 933 {
Azure.IoT Build 0:6ae2f7bca550 934 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
Azure.IoT Build 0:6ae2f7bca550 935
Azure.IoT Build 0:6ae2f7bca550 936 if (sasl_client_io_instance->io_state != IO_STATE_NOT_OPEN)
Azure.IoT Build 0:6ae2f7bca550 937 {
Azure.IoT Build 0:6ae2f7bca550 938 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 939 }
Azure.IoT Build 0:6ae2f7bca550 940 else
Azure.IoT Build 0:6ae2f7bca550 941 {
Azure.IoT Build 0:6ae2f7bca550 942 sasl_client_io_instance->on_bytes_received = on_bytes_received;
Azure.IoT Build 0:6ae2f7bca550 943 sasl_client_io_instance->on_io_open_complete = on_io_open_complete;
Azure.IoT Build 0:6ae2f7bca550 944 sasl_client_io_instance->on_io_error = on_io_error;
Azure.IoT Build 0:6ae2f7bca550 945 sasl_client_io_instance->on_bytes_received_context = on_bytes_received_context;
Azure.IoT Build 0:6ae2f7bca550 946 sasl_client_io_instance->on_io_open_complete_context = on_io_open_complete_context;
Azure.IoT Build 0:6ae2f7bca550 947 sasl_client_io_instance->on_io_error_context = on_io_error_context;
Azure.IoT Build 0:6ae2f7bca550 948 sasl_client_io_instance->sasl_header_exchange_state = SASL_HEADER_EXCHANGE_IDLE;
Azure.IoT Build 0:6ae2f7bca550 949 sasl_client_io_instance->sasl_client_negotiation_state = SASL_CLIENT_NEGOTIATION_NOT_STARTED;
Azure.IoT Build 0:6ae2f7bca550 950 sasl_client_io_instance->header_bytes_received = 0;
Azure.IoT Build 0:6ae2f7bca550 951 sasl_client_io_instance->io_state = IO_STATE_OPENING_UNDERLYING_IO;
Azure.IoT Build 0:6ae2f7bca550 952
Azure.IoT Build 0:6ae2f7bca550 953 /* Codes_SRS_SASLCLIENTIO_01_009: [saslclientio_open shall call xio_open on the underlying_io passed to saslclientio_create.] */
Azure.IoT Build 0:6ae2f7bca550 954 /* Codes_SRS_SASLCLIENTIO_01_013: [saslclientio_open shall pass to xio_open a callback for receiving bytes and a state changed callback for the underlying_io state changes.] */
Azure.IoT Build 0:6ae2f7bca550 955 if (xio_open(sasl_client_io_instance->underlying_io, on_underlying_io_open_complete, sasl_client_io_instance, on_underlying_io_bytes_received, sasl_client_io_instance, on_underlying_io_error, sasl_client_io_instance) != 0)
Azure.IoT Build 0:6ae2f7bca550 956 {
Azure.IoT Build 0:6ae2f7bca550 957 /* Codes_SRS_SASLCLIENTIO_01_012: [If the open of the underlying_io fails, saslclientio_open shall fail and return non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 958 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 959 }
Azure.IoT Build 0:6ae2f7bca550 960 else
Azure.IoT Build 0:6ae2f7bca550 961 {
Azure.IoT Build 0:6ae2f7bca550 962 /* Codes_SRS_SASLCLIENTIO_01_010: [On success, saslclientio_open shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 963 result = 0;
Azure.IoT Build 0:6ae2f7bca550 964 }
Azure.IoT Build 0:6ae2f7bca550 965 }
Azure.IoT Build 0:6ae2f7bca550 966 }
Azure.IoT Build 0:6ae2f7bca550 967
Azure.IoT Build 0:6ae2f7bca550 968 return result;
Azure.IoT Build 0:6ae2f7bca550 969 }
Azure.IoT Build 0:6ae2f7bca550 970
Azure.IoT Build 0:6ae2f7bca550 971 int saslclientio_close(CONCRETE_IO_HANDLE sasl_client_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* on_io_close_complete_context)
Azure.IoT Build 0:6ae2f7bca550 972 {
Azure.IoT Build 0:6ae2f7bca550 973 int result = 0;
Azure.IoT Build 0:6ae2f7bca550 974
Azure.IoT Build 0:6ae2f7bca550 975 /* Codes_SRS_SASLCLIENTIO_01_017: [If sasl_client_io is NULL, saslclientio_close shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 976 if (sasl_client_io == NULL)
Azure.IoT Build 0:6ae2f7bca550 977 {
Azure.IoT Build 0:6ae2f7bca550 978 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 979 }
Azure.IoT Build 0:6ae2f7bca550 980 else
Azure.IoT Build 0:6ae2f7bca550 981 {
Azure.IoT Build 0:6ae2f7bca550 982 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
Azure.IoT Build 0:6ae2f7bca550 983
Azure.IoT Build 0:6ae2f7bca550 984 /* Codes_SRS_SASLCLIENTIO_01_098: [saslclientio_close shall only perform the close if the state is OPEN, OPENING or ERROR.] */
Azure.IoT Build 0:6ae2f7bca550 985 if ((sasl_client_io_instance->io_state == IO_STATE_NOT_OPEN) ||
Azure.IoT Build 0:6ae2f7bca550 986 (sasl_client_io_instance->io_state == IO_STATE_CLOSING))
Azure.IoT Build 0:6ae2f7bca550 987 {
Azure.IoT Build 0:6ae2f7bca550 988 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 989 }
Azure.IoT Build 0:6ae2f7bca550 990 else
Azure.IoT Build 0:6ae2f7bca550 991 {
Azure.IoT Build 0:6ae2f7bca550 992 sasl_client_io_instance->io_state = IO_STATE_CLOSING;
Azure.IoT Build 0:6ae2f7bca550 993
Azure.IoT Build 0:6ae2f7bca550 994 sasl_client_io_instance->on_io_close_complete = on_io_close_complete;
Azure.IoT Build 0:6ae2f7bca550 995 sasl_client_io_instance->on_io_close_complete_context = on_io_close_complete_context;
Azure.IoT Build 0:6ae2f7bca550 996
Azure.IoT Build 0:6ae2f7bca550 997 /* Codes_SRS_SASLCLIENTIO_01_015: [saslclientio_close shall close the underlying io handle passed in saslclientio_create by calling xio_close.] */
Azure.IoT Build 0:6ae2f7bca550 998 if (xio_close(sasl_client_io_instance->underlying_io, on_underlying_io_close_complete, sasl_client_io_instance) != 0)
Azure.IoT Build 0:6ae2f7bca550 999 {
Azure.IoT Build 0:6ae2f7bca550 1000 /* Codes_SRS_SASLCLIENTIO_01_018: [If xio_close fails, then saslclientio_close shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 1001 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 1002 }
Azure.IoT Build 0:6ae2f7bca550 1003 else
Azure.IoT Build 0:6ae2f7bca550 1004 {
Azure.IoT Build 0:6ae2f7bca550 1005 /* Codes_SRS_SASLCLIENTIO_01_016: [On success, saslclientio_close shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 1006 result = 0;
Azure.IoT Build 0:6ae2f7bca550 1007 }
Azure.IoT Build 0:6ae2f7bca550 1008 }
Azure.IoT Build 0:6ae2f7bca550 1009 }
Azure.IoT Build 0:6ae2f7bca550 1010
Azure.IoT Build 0:6ae2f7bca550 1011 return result;
Azure.IoT Build 0:6ae2f7bca550 1012 }
Azure.IoT Build 0:6ae2f7bca550 1013
Azure.IoT Build 0:6ae2f7bca550 1014 int saslclientio_send(CONCRETE_IO_HANDLE sasl_client_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 1015 {
Azure.IoT Build 0:6ae2f7bca550 1016 int result;
Azure.IoT Build 0:6ae2f7bca550 1017
Azure.IoT Build 0:6ae2f7bca550 1018 /* Codes_SRS_SASLCLIENTIO_01_022: [If the saslio or buffer argument is NULL, saslclientio_send shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 1019 if ((sasl_client_io == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 1020 (buffer == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 1021 /* Codes_SRS_SASLCLIENTIO_01_023: [If size is 0, saslclientio_send shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 1022 (size == 0))
Azure.IoT Build 0:6ae2f7bca550 1023 {
Azure.IoT Build 0:6ae2f7bca550 1024 /* Invalid arguments */
Azure.IoT Build 0:6ae2f7bca550 1025 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 1026 }
Azure.IoT Build 0:6ae2f7bca550 1027 else
Azure.IoT Build 0:6ae2f7bca550 1028 {
Azure.IoT Build 0:6ae2f7bca550 1029 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
Azure.IoT Build 0:6ae2f7bca550 1030
Azure.IoT Build 0:6ae2f7bca550 1031 if (sasl_client_io_instance->logger_log != NULL)
Azure.IoT Build 0:6ae2f7bca550 1032 {
Azure.IoT Build 0:6ae2f7bca550 1033 size_t i;
Azure.IoT Build 0:6ae2f7bca550 1034 for (i = 0; i < size; i++)
Azure.IoT Build 0:6ae2f7bca550 1035 {
Azure.IoT Build 0:6ae2f7bca550 1036 LOG(sasl_client_io_instance->logger_log, 0, " %02x", ((const unsigned char*)buffer)[i]);
Azure.IoT Build 0:6ae2f7bca550 1037 }
Azure.IoT Build 0:6ae2f7bca550 1038 }
Azure.IoT Build 0:6ae2f7bca550 1039
Azure.IoT Build 0:6ae2f7bca550 1040 /* Codes_SRS_SASLCLIENTIO_01_019: [If saslclientio_send is called while the SASL client IO state is not IO_STATE_OPEN, saslclientio_send shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 1041 if (sasl_client_io_instance->io_state != IO_STATE_OPEN)
Azure.IoT Build 0:6ae2f7bca550 1042 {
Azure.IoT Build 0:6ae2f7bca550 1043 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 1044 }
Azure.IoT Build 0:6ae2f7bca550 1045 else
Azure.IoT Build 0:6ae2f7bca550 1046 {
Azure.IoT Build 0:6ae2f7bca550 1047 /* Codes_SRS_SASLCLIENTIO_01_020: [If the SASL client IO state is IO_STATE_OPEN, saslclientio_send shall call xio_send on the underlying_io passed to saslclientio_create, while passing as arguments the buffer, size, on_send_complete and callback_context.] */
Azure.IoT Build 0:6ae2f7bca550 1048 if (xio_send(sasl_client_io_instance->underlying_io, buffer, size, on_send_complete, callback_context) != 0)
Azure.IoT Build 0:6ae2f7bca550 1049 {
Azure.IoT Build 0:6ae2f7bca550 1050 /* Codes_SRS_SASLCLIENTIO_01_024: [If the call to xio_send fails, then saslclientio_send shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 1051 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 1052 }
Azure.IoT Build 0:6ae2f7bca550 1053 else
Azure.IoT Build 0:6ae2f7bca550 1054 {
Azure.IoT Build 0:6ae2f7bca550 1055 /* Codes_SRS_SASLCLIENTIO_01_021: [On success, saslclientio_send shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 1056 result = 0;
Azure.IoT Build 0:6ae2f7bca550 1057 }
Azure.IoT Build 0:6ae2f7bca550 1058 }
Azure.IoT Build 0:6ae2f7bca550 1059 }
Azure.IoT Build 0:6ae2f7bca550 1060
Azure.IoT Build 0:6ae2f7bca550 1061 return result;
Azure.IoT Build 0:6ae2f7bca550 1062 }
Azure.IoT Build 0:6ae2f7bca550 1063
Azure.IoT Build 0:6ae2f7bca550 1064 void saslclientio_dowork(CONCRETE_IO_HANDLE sasl_client_io)
Azure.IoT Build 0:6ae2f7bca550 1065 {
Azure.IoT Build 0:6ae2f7bca550 1066 /* Codes_SRS_SASLCLIENTIO_01_026: [If the sasl_client_io argument is NULL, saslclientio_dowork shall do nothing.] */
Azure.IoT Build 0:6ae2f7bca550 1067 if (sasl_client_io != NULL)
Azure.IoT Build 0:6ae2f7bca550 1068 {
Azure.IoT Build 0:6ae2f7bca550 1069 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
Azure.IoT Build 0:6ae2f7bca550 1070
Azure.IoT Build 0:6ae2f7bca550 1071 /* Codes_SRS_SASLCLIENTIO_01_025: [saslclientio_dowork shall call the xio_dowork on the underlying_io passed in saslclientio_create.] */
Azure.IoT Build 0:6ae2f7bca550 1072 if (sasl_client_io_instance->io_state != IO_STATE_NOT_OPEN)
Azure.IoT Build 0:6ae2f7bca550 1073 {
Azure.IoT Build 0:6ae2f7bca550 1074 /* Codes_SRS_SASLCLIENTIO_01_025: [saslclientio_dowork shall call the xio_dowork on the underlying_io passed in saslclientio_create.] */
Azure.IoT Build 0:6ae2f7bca550 1075 xio_dowork(sasl_client_io_instance->underlying_io);
Azure.IoT Build 0:6ae2f7bca550 1076 }
Azure.IoT Build 0:6ae2f7bca550 1077 }
Azure.IoT Build 0:6ae2f7bca550 1078 }
Azure.IoT Build 0:6ae2f7bca550 1079
AzureIoTClient 1:eab586236bfe 1080 /* Codes_SRS_SASLCLIENTIO_03_001: [saslclientio_setoption shall forward options to underlying io.]*/
AzureIoTClient 1:eab586236bfe 1081 int saslclientio_setoption(CONCRETE_IO_HANDLE sasl_client_io, const char* optionName, const void* value)
Azure.IoT Build 0:6ae2f7bca550 1082 {
AzureIoTClient 1:eab586236bfe 1083 int result;
AzureIoTClient 1:eab586236bfe 1084
AzureIoTClient 1:eab586236bfe 1085 if (sasl_client_io == NULL)
AzureIoTClient 1:eab586236bfe 1086 {
AzureIoTClient 1:eab586236bfe 1087 result = __LINE__;
AzureIoTClient 1:eab586236bfe 1088 }
AzureIoTClient 1:eab586236bfe 1089 else
AzureIoTClient 1:eab586236bfe 1090 {
AzureIoTClient 1:eab586236bfe 1091 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
AzureIoTClient 1:eab586236bfe 1092
AzureIoTClient 1:eab586236bfe 1093 if (sasl_client_io_instance->underlying_io == NULL)
AzureIoTClient 1:eab586236bfe 1094 {
AzureIoTClient 1:eab586236bfe 1095 result = __LINE__;
AzureIoTClient 1:eab586236bfe 1096 }
AzureIoTClient 1:eab586236bfe 1097 else
AzureIoTClient 1:eab586236bfe 1098 {
AzureIoTClient 1:eab586236bfe 1099 result = xio_setoption(sasl_client_io_instance->underlying_io, optionName, value);
AzureIoTClient 1:eab586236bfe 1100 }
AzureIoTClient 1:eab586236bfe 1101 }
AzureIoTClient 1:eab586236bfe 1102
AzureIoTClient 1:eab586236bfe 1103 return result;
Azure.IoT Build 0:6ae2f7bca550 1104 }
Azure.IoT Build 0:6ae2f7bca550 1105
Azure.IoT Build 0:6ae2f7bca550 1106 static const IO_INTERFACE_DESCRIPTION sasl_client_io_interface_description =
Azure.IoT Build 0:6ae2f7bca550 1107 {
Azure.IoT Build 0:6ae2f7bca550 1108 saslclientio_create,
Azure.IoT Build 0:6ae2f7bca550 1109 saslclientio_destroy,
Azure.IoT Build 0:6ae2f7bca550 1110 saslclientio_open,
Azure.IoT Build 0:6ae2f7bca550 1111 saslclientio_close,
Azure.IoT Build 0:6ae2f7bca550 1112 saslclientio_send,
Azure.IoT Build 0:6ae2f7bca550 1113 saslclientio_dowork,
Azure.IoT Build 0:6ae2f7bca550 1114 saslclientio_setoption
Azure.IoT Build 0:6ae2f7bca550 1115 };
Azure.IoT Build 0:6ae2f7bca550 1116
Azure.IoT Build 0:6ae2f7bca550 1117 /* Codes_SRS_SASLCLIENTIO_01_087: [saslclientio_get_interface_description shall return a pointer to an IO_INTERFACE_DESCRIPTION structure that contains pointers to the functions: saslclientio_create, saslclientio_destroy, saslclientio_open, saslclientio_close, saslclientio_send and saslclientio_dowork.] */
Azure.IoT Build 0:6ae2f7bca550 1118 const IO_INTERFACE_DESCRIPTION* saslclientio_get_interface_description(void)
Azure.IoT Build 0:6ae2f7bca550 1119 {
Azure.IoT Build 0:6ae2f7bca550 1120 return &sasl_client_io_interface_description;
Azure.IoT Build 0:6ae2f7bca550 1121 }