A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Mon May 08 10:50:45 2017 -0700
Revision:
24:2c59c2d43ebf
Parent:
23:1111ee8bcba4
Child:
28:add19eb7defa
1.1.14

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 #include <string.h>
AzureIoTClient 19:000ab4e6a2c1 6 #include "azure_c_shared_utility/optimize_size.h"
AzureIoTClient 20:206846c14c80 7 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 23:1111ee8bcba4 8 #include "azure_c_shared_utility/xlogging.h"
Azure.IoT Build 0:6ae2f7bca550 9 #include "azure_uamqp_c/sasl_plain.h"
Azure.IoT Build 0:6ae2f7bca550 10
Azure.IoT Build 0:6ae2f7bca550 11 typedef struct SASL_PLAIN_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 12 {
Azure.IoT Build 0:6ae2f7bca550 13 unsigned char* init_bytes;
AzureIoTClient 6:641a9672db08 14 uint32_t init_bytes_length;
Azure.IoT Build 0:6ae2f7bca550 15 } SASL_PLAIN_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 16
Azure.IoT Build 0:6ae2f7bca550 17 CONCRETE_SASL_MECHANISM_HANDLE saslplain_create(void* config)
Azure.IoT Build 0:6ae2f7bca550 18 {
Azure.IoT Build 0:6ae2f7bca550 19 SASL_PLAIN_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 20
Azure.IoT Build 0:6ae2f7bca550 21 if (config == NULL)
Azure.IoT Build 0:6ae2f7bca550 22 {
AzureIoTClient 24:2c59c2d43ebf 23 /* Codes_SRS_SASL_PLAIN_01_003: [If the `config` argument is NULL, then `saslplain_create` shall fail and return NULL.] */
AzureIoTClient 23:1111ee8bcba4 24 LogError("NULL config");
Azure.IoT Build 0:6ae2f7bca550 25 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 26 }
Azure.IoT Build 0:6ae2f7bca550 27 else
Azure.IoT Build 0:6ae2f7bca550 28 {
Azure.IoT Build 0:6ae2f7bca550 29 SASL_PLAIN_CONFIG* sasl_plain_config = (SASL_PLAIN_CONFIG*)config;
Azure.IoT Build 0:6ae2f7bca550 30
AzureIoTClient 24:2c59c2d43ebf 31 /* Codes_SRS_SASL_PLAIN_01_025: [ `authzid` shall be optional. ]*/
Azure.IoT Build 0:6ae2f7bca550 32 if ((sasl_plain_config->authcid == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 33 (sasl_plain_config->passwd == NULL))
Azure.IoT Build 0:6ae2f7bca550 34 {
AzureIoTClient 24:2c59c2d43ebf 35 /* Codes_SRS_SASL_PLAIN_01_004: [If either the `authcid` or `passwd` member of the `config` structure is NULL, then `saslplain_create` shall fail and return NULL.] */
AzureIoTClient 24:2c59c2d43ebf 36 LogError("Bad configuration: authcid = %p, passwd = %p",
AzureIoTClient 23:1111ee8bcba4 37 sasl_plain_config->authcid, sasl_plain_config->passwd);
AzureIoTClient 23:1111ee8bcba4 38 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 39 }
Azure.IoT Build 0:6ae2f7bca550 40 else
Azure.IoT Build 0:6ae2f7bca550 41 {
Azure.IoT Build 0:6ae2f7bca550 42 size_t authzid_length = sasl_plain_config->authzid == NULL ? 0 : strlen(sasl_plain_config->authzid);
Azure.IoT Build 0:6ae2f7bca550 43 size_t authcid_length = strlen(sasl_plain_config->authcid);
Azure.IoT Build 0:6ae2f7bca550 44 size_t passwd_length = strlen(sasl_plain_config->passwd);
Azure.IoT Build 0:6ae2f7bca550 45
Azure.IoT Build 0:6ae2f7bca550 46 /* Codes_SRS_SASL_PLAIN_01_020: [ authcid = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 47 if ((authcid_length > 255) || (authcid_length == 0) ||
Azure.IoT Build 0:6ae2f7bca550 48 /* Codes_SRS_SASL_PLAIN_01_021: [ authzid = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 49 (authzid_length > 255) ||
Azure.IoT Build 0:6ae2f7bca550 50 /* Codes_SRS_SASL_PLAIN_01_022: [ passwd = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 51 (passwd_length > 255) || (passwd_length == 0))
Azure.IoT Build 0:6ae2f7bca550 52 {
AzureIoTClient 23:1111ee8bcba4 53 LogError("Bad configuration: authcid length = %u, passwd length = %u",
AzureIoTClient 23:1111ee8bcba4 54 (unsigned int)authcid_length, (unsigned int)passwd_length);
AzureIoTClient 23:1111ee8bcba4 55 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 56 }
Azure.IoT Build 0:6ae2f7bca550 57 else
Azure.IoT Build 0:6ae2f7bca550 58 {
AzureIoTClient 24:2c59c2d43ebf 59 /* Codes_SRS_SASL_PLAIN_01_001: [`saslplain_create` shall return on success a non-NULL handle to a new SASL plain mechanism.] */
AzureIoTClient 23:1111ee8bcba4 60 result = (SASL_PLAIN_INSTANCE*)malloc(sizeof(SASL_PLAIN_INSTANCE));
AzureIoTClient 24:2c59c2d43ebf 61 if (result == NULL)
AzureIoTClient 24:2c59c2d43ebf 62 {
AzureIoTClient 24:2c59c2d43ebf 63 /* Codes_SRS_SASL_PLAIN_01_002: [If allocating the memory needed for the saslplain instance fails then `saslplain_create` shall return NULL.] */
AzureIoTClient 24:2c59c2d43ebf 64 LogError("Cannot allocate memory for SASL plain instance");
AzureIoTClient 24:2c59c2d43ebf 65 }
AzureIoTClient 24:2c59c2d43ebf 66 else
Azure.IoT Build 0:6ae2f7bca550 67 {
Azure.IoT Build 0:6ae2f7bca550 68 /* Ignore UTF8 for now */
AzureIoTClient 20:206846c14c80 69 result->init_bytes = (unsigned char*)malloc(authzid_length + authcid_length + passwd_length + 2);
Azure.IoT Build 0:6ae2f7bca550 70 if (result->init_bytes == NULL)
Azure.IoT Build 0:6ae2f7bca550 71 {
AzureIoTClient 24:2c59c2d43ebf 72 /* Codes_SRS_SASL_PLAIN_01_002: [If allocating the memory needed for the saslplain instance fails then `saslplain_create` shall return NULL.] */
AzureIoTClient 23:1111ee8bcba4 73 LogError("Cannot allocate init bytes");
AzureIoTClient 23:1111ee8bcba4 74 free(result);
Azure.IoT Build 0:6ae2f7bca550 75 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 76 }
Azure.IoT Build 0:6ae2f7bca550 77 else
Azure.IoT Build 0:6ae2f7bca550 78 {
Azure.IoT Build 0:6ae2f7bca550 79 /* Codes_SRS_SASL_PLAIN_01_016: [The mechanism consists of a single message, a string of [UTF-8] encoded [Unicode] characters, from the client to the server.] */
Azure.IoT Build 0:6ae2f7bca550 80 /* Codes_SRS_SASL_PLAIN_01_017: [The client presents the authorization identity (identity to act as), followed by a NUL (U+0000) character, followed by the authentication identity (identity whose password will be used), followed by a NUL (U+0000) character, followed by the clear-text password.] */
Azure.IoT Build 0:6ae2f7bca550 81 /* Codes_SRS_SASL_PLAIN_01_019: [ message = [authzid] UTF8NUL authcid UTF8NUL passwd] */
Azure.IoT Build 0:6ae2f7bca550 82 /* Codes_SRS_SASL_PLAIN_01_023: [The authorization identity (authzid), authentication identity (authcid), password (passwd), and NUL character deliminators SHALL be transferred as [UTF-8] encoded strings of [Unicode] characters.] */
Azure.IoT Build 0:6ae2f7bca550 83 /* Codes_SRS_SASL_PLAIN_01_024: [As the NUL (U+0000) character is used as a deliminator, the NUL (U+0000) character MUST NOT appear in authzid, authcid, or passwd productions.] */
Azure.IoT Build 0:6ae2f7bca550 84
Azure.IoT Build 0:6ae2f7bca550 85 /* Codes_SRS_SASL_PLAIN_01_018: [As with other SASL mechanisms, the client does not provide an authorization identity when it wishes the server to derive an identity from the credentials and use that as the authorization identity.] */
Azure.IoT Build 0:6ae2f7bca550 86 if (authzid_length > 0)
Azure.IoT Build 0:6ae2f7bca550 87 {
Azure.IoT Build 0:6ae2f7bca550 88 (void)memcpy(result->init_bytes, sasl_plain_config->authzid, authzid_length);
Azure.IoT Build 0:6ae2f7bca550 89 }
Azure.IoT Build 0:6ae2f7bca550 90
Azure.IoT Build 0:6ae2f7bca550 91 result->init_bytes[authzid_length] = 0;
Azure.IoT Build 0:6ae2f7bca550 92 (void)memcpy(result->init_bytes + authzid_length + 1, sasl_plain_config->authcid, authcid_length);
Azure.IoT Build 0:6ae2f7bca550 93 result->init_bytes[authzid_length + authcid_length + 1] = 0;
Azure.IoT Build 0:6ae2f7bca550 94 (void)memcpy(result->init_bytes + authzid_length + authcid_length + 2, sasl_plain_config->passwd, passwd_length);
AzureIoTClient 6:641a9672db08 95 result->init_bytes_length = (uint32_t)(authzid_length + authcid_length + passwd_length + 2);
Azure.IoT Build 0:6ae2f7bca550 96 }
Azure.IoT Build 0:6ae2f7bca550 97 }
Azure.IoT Build 0:6ae2f7bca550 98 }
Azure.IoT Build 0:6ae2f7bca550 99 }
Azure.IoT Build 0:6ae2f7bca550 100 }
Azure.IoT Build 0:6ae2f7bca550 101
Azure.IoT Build 0:6ae2f7bca550 102 return result;
Azure.IoT Build 0:6ae2f7bca550 103 }
Azure.IoT Build 0:6ae2f7bca550 104
Azure.IoT Build 0:6ae2f7bca550 105 void saslplain_destroy(CONCRETE_SASL_MECHANISM_HANDLE sasl_mechanism_concrete_handle)
Azure.IoT Build 0:6ae2f7bca550 106 {
AzureIoTClient 23:1111ee8bcba4 107 if (sasl_mechanism_concrete_handle == NULL)
AzureIoTClient 23:1111ee8bcba4 108 {
AzureIoTClient 24:2c59c2d43ebf 109 /* Codes_SRS_SASL_PLAIN_01_006: [If the argument `concrete_sasl_mechanism` is NULL, `saslplain_destroy` shall do nothing.] */
AzureIoTClient 24:2c59c2d43ebf 110 LogError("NULL sasl_mechanism_concrete_handle");
AzureIoTClient 23:1111ee8bcba4 111 }
AzureIoTClient 23:1111ee8bcba4 112 else
AzureIoTClient 23:1111ee8bcba4 113 {
AzureIoTClient 24:2c59c2d43ebf 114 /* Codes_SRS_SASL_PLAIN_01_005: [`saslplain_destroy` shall free all resources associated with the SASL mechanism.] */
Azure.IoT Build 0:6ae2f7bca550 115 SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle;
Azure.IoT Build 0:6ae2f7bca550 116 if (sasl_plain_instance->init_bytes != NULL)
Azure.IoT Build 0:6ae2f7bca550 117 {
AzureIoTClient 20:206846c14c80 118 free(sasl_plain_instance->init_bytes);
Azure.IoT Build 0:6ae2f7bca550 119 }
Azure.IoT Build 0:6ae2f7bca550 120
AzureIoTClient 20:206846c14c80 121 free(sasl_plain_instance);
Azure.IoT Build 0:6ae2f7bca550 122 }
Azure.IoT Build 0:6ae2f7bca550 123 }
Azure.IoT Build 0:6ae2f7bca550 124
Azure.IoT Build 0:6ae2f7bca550 125 int saslplain_get_init_bytes(CONCRETE_SASL_MECHANISM_HANDLE sasl_mechanism_concrete_handle, SASL_MECHANISM_BYTES* init_bytes)
Azure.IoT Build 0:6ae2f7bca550 126 {
Azure.IoT Build 0:6ae2f7bca550 127 int result;
Azure.IoT Build 0:6ae2f7bca550 128
Azure.IoT Build 0:6ae2f7bca550 129 if ((sasl_mechanism_concrete_handle == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 130 (init_bytes == NULL))
Azure.IoT Build 0:6ae2f7bca550 131 {
AzureIoTClient 24:2c59c2d43ebf 132 /* Codes_SRS_SASL_PLAIN_01_009: [If any argument is NULL, `saslplain_get_init_bytes` shall return a non-zero value.] */
AzureIoTClient 24:2c59c2d43ebf 133 LogError("Bad arguments: sasl_mechanism_concrete_handle = %p, init_bytes = %p",
AzureIoTClient 23:1111ee8bcba4 134 sasl_mechanism_concrete_handle, init_bytes);
AzureIoTClient 23:1111ee8bcba4 135 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 136 }
Azure.IoT Build 0:6ae2f7bca550 137 else
Azure.IoT Build 0:6ae2f7bca550 138 {
Azure.IoT Build 0:6ae2f7bca550 139 SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle;
Azure.IoT Build 0:6ae2f7bca550 140
AzureIoTClient 24:2c59c2d43ebf 141 /* Codes_SRS_SASL_PLAIN_01_007: [`saslplain_get_init_bytes` shall construct the initial bytes per the RFC 4616.] */
Azure.IoT Build 0:6ae2f7bca550 142 init_bytes->bytes = sasl_plain_instance->init_bytes;
Azure.IoT Build 0:6ae2f7bca550 143 init_bytes->length = sasl_plain_instance->init_bytes_length;
Azure.IoT Build 0:6ae2f7bca550 144
AzureIoTClient 24:2c59c2d43ebf 145 /* Codes_SRS_SASL_PLAIN_01_008: [On success `saslplain_get_init_bytes` shall return zero.] */
Azure.IoT Build 0:6ae2f7bca550 146 result = 0;
Azure.IoT Build 0:6ae2f7bca550 147 }
Azure.IoT Build 0:6ae2f7bca550 148
Azure.IoT Build 0:6ae2f7bca550 149 return result;
Azure.IoT Build 0:6ae2f7bca550 150 }
Azure.IoT Build 0:6ae2f7bca550 151
Azure.IoT Build 0:6ae2f7bca550 152 const char* saslplain_get_mechanism_name(CONCRETE_SASL_MECHANISM_HANDLE sasl_mechanism)
Azure.IoT Build 0:6ae2f7bca550 153 {
Azure.IoT Build 0:6ae2f7bca550 154 const char* result;
Azure.IoT Build 0:6ae2f7bca550 155
Azure.IoT Build 0:6ae2f7bca550 156 if (sasl_mechanism == NULL)
Azure.IoT Build 0:6ae2f7bca550 157 {
AzureIoTClient 24:2c59c2d43ebf 158 /* Codes_SRS_SASL_PLAIN_01_011: [If the argument `concrete_sasl_mechanism` is NULL, `saslplain_get_mechanism_name` shall return NULL.] */
AzureIoTClient 23:1111ee8bcba4 159 LogError("NULL sasl_mechanism");
AzureIoTClient 23:1111ee8bcba4 160 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 161 }
Azure.IoT Build 0:6ae2f7bca550 162 else
Azure.IoT Build 0:6ae2f7bca550 163 {
AzureIoTClient 24:2c59c2d43ebf 164 /* Codes_SRS_SASL_PLAIN_01_010: [`saslplain_get_mechanism_name` shall validate the argument `concrete_sasl_mechanism` and on success it shall return a pointer to the string "PLAIN".] */
Azure.IoT Build 0:6ae2f7bca550 165 result = "PLAIN";
Azure.IoT Build 0:6ae2f7bca550 166 }
Azure.IoT Build 0:6ae2f7bca550 167
Azure.IoT Build 0:6ae2f7bca550 168 return result;
Azure.IoT Build 0:6ae2f7bca550 169 }
Azure.IoT Build 0:6ae2f7bca550 170
Azure.IoT Build 0:6ae2f7bca550 171 int saslplain_challenge(CONCRETE_SASL_MECHANISM_HANDLE concrete_sasl_mechanism, const SASL_MECHANISM_BYTES* challenge_bytes, SASL_MECHANISM_BYTES* response_bytes)
Azure.IoT Build 0:6ae2f7bca550 172 {
Azure.IoT Build 0:6ae2f7bca550 173 int result;
Azure.IoT Build 0:6ae2f7bca550 174
Azure.IoT Build 0:6ae2f7bca550 175 (void)challenge_bytes;
Azure.IoT Build 0:6ae2f7bca550 176
AzureIoTClient 24:2c59c2d43ebf 177 /* Codes_SRS_SASL_PLAIN_01_014: [If the `concrete_sasl_mechanism` or `response_bytes` argument is NULL then `saslplain_challenge` shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 178 if ((concrete_sasl_mechanism == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 179 (response_bytes == NULL))
Azure.IoT Build 0:6ae2f7bca550 180 {
AzureIoTClient 23:1111ee8bcba4 181 LogError("Bad arguments: concrete_sasl_mechanism = %p, response_bytes = %p",
AzureIoTClient 23:1111ee8bcba4 182 concrete_sasl_mechanism, response_bytes);
AzureIoTClient 23:1111ee8bcba4 183 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 184 }
Azure.IoT Build 0:6ae2f7bca550 185 else
Azure.IoT Build 0:6ae2f7bca550 186 {
AzureIoTClient 24:2c59c2d43ebf 187 /* Codes_SRS_SASL_PLAIN_01_012: [`saslplain_challenge` shall set the `response_bytes` buffer to NULL and 0 size as the PLAIN SASL mechanism does not implement challenge/response.] */
Azure.IoT Build 0:6ae2f7bca550 188 response_bytes->bytes = NULL;
Azure.IoT Build 0:6ae2f7bca550 189 response_bytes->length = 0;
Azure.IoT Build 0:6ae2f7bca550 190
AzureIoTClient 24:2c59c2d43ebf 191 /* Codes_SRS_SASL_PLAIN_01_013: [On success, `saslplain_challenge` shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 192 result = 0;
Azure.IoT Build 0:6ae2f7bca550 193 }
Azure.IoT Build 0:6ae2f7bca550 194
Azure.IoT Build 0:6ae2f7bca550 195 return result;
Azure.IoT Build 0:6ae2f7bca550 196 }
Azure.IoT Build 0:6ae2f7bca550 197
AzureIoTClient 24:2c59c2d43ebf 198 static const SASL_MECHANISM_INTERFACE_DESCRIPTION saslplain_interface =
AzureIoTClient 24:2c59c2d43ebf 199 {
AzureIoTClient 24:2c59c2d43ebf 200 /* Codes_SRS_SASL_PLAIN_01_015: [**`saslplain_get_interface` shall return a pointer to a `SASL_MECHANISM_INTERFACE_DESCRIPTION` structure that contains pointers to the functions: `saslplain_create`, `saslplain_destroy`, `saslplain_get_init_bytes`, `saslplain_get_mechanism_name`, `saslplain_challenge`.] */
AzureIoTClient 24:2c59c2d43ebf 201 saslplain_create,
AzureIoTClient 24:2c59c2d43ebf 202 saslplain_destroy,
AzureIoTClient 24:2c59c2d43ebf 203 saslplain_get_init_bytes,
AzureIoTClient 24:2c59c2d43ebf 204 saslplain_get_mechanism_name,
AzureIoTClient 24:2c59c2d43ebf 205 saslplain_challenge
AzureIoTClient 24:2c59c2d43ebf 206 };
AzureIoTClient 24:2c59c2d43ebf 207
Azure.IoT Build 0:6ae2f7bca550 208 const SASL_MECHANISM_INTERFACE_DESCRIPTION* saslplain_get_interface(void)
Azure.IoT Build 0:6ae2f7bca550 209 {
Azure.IoT Build 0:6ae2f7bca550 210 return &saslplain_interface;
Azure.IoT Build 0:6ae2f7bca550 211 }