A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Jun 30 10:41:22 2017 -0700
Revision:
28:add19eb7defa
Parent:
24:2c59c2d43ebf
1.1.18

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 {
AzureIoTClient 28:add19eb7defa 13 unsigned char* init_bytes;
AzureIoTClient 28:add19eb7defa 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 {
AzureIoTClient 28:add19eb7defa 19 SASL_PLAIN_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 20
AzureIoTClient 28:add19eb7defa 21 if (config == NULL)
AzureIoTClient 28:add19eb7defa 22 {
AzureIoTClient 28:add19eb7defa 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");
AzureIoTClient 28:add19eb7defa 25 result = NULL;
AzureIoTClient 28:add19eb7defa 26 }
AzureIoTClient 28:add19eb7defa 27 else
AzureIoTClient 28:add19eb7defa 28 {
AzureIoTClient 28:add19eb7defa 29 SASL_PLAIN_CONFIG* sasl_plain_config = (SASL_PLAIN_CONFIG*)config;
Azure.IoT Build 0:6ae2f7bca550 30
AzureIoTClient 28:add19eb7defa 31 /* Codes_SRS_SASL_PLAIN_01_025: [ `authzid` shall be optional. ]*/
AzureIoTClient 28:add19eb7defa 32 if ((sasl_plain_config->authcid == NULL) ||
AzureIoTClient 28:add19eb7defa 33 (sasl_plain_config->passwd == NULL))
AzureIoTClient 28:add19eb7defa 34 {
AzureIoTClient 28:add19eb7defa 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 28:add19eb7defa 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;
AzureIoTClient 28:add19eb7defa 39 }
AzureIoTClient 28:add19eb7defa 40 else
AzureIoTClient 28:add19eb7defa 41 {
AzureIoTClient 28:add19eb7defa 42 size_t authzid_length = sasl_plain_config->authzid == NULL ? 0 : strlen(sasl_plain_config->authzid);
AzureIoTClient 28:add19eb7defa 43 size_t authcid_length = strlen(sasl_plain_config->authcid);
AzureIoTClient 28:add19eb7defa 44 size_t passwd_length = strlen(sasl_plain_config->passwd);
Azure.IoT Build 0:6ae2f7bca550 45
AzureIoTClient 28:add19eb7defa 46 /* Codes_SRS_SASL_PLAIN_01_020: [ authcid = 1*SAFE ; MUST accept up to 255 octets] */
AzureIoTClient 28:add19eb7defa 47 if ((authcid_length > 255) || (authcid_length == 0) ||
AzureIoTClient 28:add19eb7defa 48 /* Codes_SRS_SASL_PLAIN_01_021: [ authzid = 1*SAFE ; MUST accept up to 255 octets] */
AzureIoTClient 28:add19eb7defa 49 (authzid_length > 255) ||
AzureIoTClient 28:add19eb7defa 50 /* Codes_SRS_SASL_PLAIN_01_022: [ passwd = 1*SAFE ; MUST accept up to 255 octets] */
AzureIoTClient 28:add19eb7defa 51 (passwd_length > 255) || (passwd_length == 0))
AzureIoTClient 28:add19eb7defa 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;
AzureIoTClient 28:add19eb7defa 56 }
AzureIoTClient 28:add19eb7defa 57 else
AzureIoTClient 28:add19eb7defa 58 {
AzureIoTClient 28:add19eb7defa 59 /* Codes_SRS_SASL_PLAIN_01_001: [`saslplain_create` shall return on success a non-NULL handle to a new SASL plain mechanism.] */
AzureIoTClient 28:add19eb7defa 60 result = (SASL_PLAIN_INSTANCE*)malloc(sizeof(SASL_PLAIN_INSTANCE));
AzureIoTClient 28:add19eb7defa 61 if (result == NULL)
AzureIoTClient 28:add19eb7defa 62 {
AzureIoTClient 28:add19eb7defa 63 /* Codes_SRS_SASL_PLAIN_01_002: [If allocating the memory needed for the saslplain instance fails then `saslplain_create` shall return NULL.] */
AzureIoTClient 28:add19eb7defa 64 LogError("Cannot allocate memory for SASL plain instance");
AzureIoTClient 28:add19eb7defa 65 }
AzureIoTClient 28:add19eb7defa 66 else
AzureIoTClient 28:add19eb7defa 67 {
AzureIoTClient 28:add19eb7defa 68 /* Ignore UTF8 for now */
AzureIoTClient 28:add19eb7defa 69 result->init_bytes = (unsigned char*)malloc(authzid_length + authcid_length + passwd_length + 2);
AzureIoTClient 28:add19eb7defa 70 if (result->init_bytes == NULL)
AzureIoTClient 28:add19eb7defa 71 {
AzureIoTClient 28:add19eb7defa 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);
AzureIoTClient 28:add19eb7defa 75 result = NULL;
AzureIoTClient 28:add19eb7defa 76 }
AzureIoTClient 28:add19eb7defa 77 else
AzureIoTClient 28:add19eb7defa 78 {
AzureIoTClient 28:add19eb7defa 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.] */
AzureIoTClient 28:add19eb7defa 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.] */
AzureIoTClient 28:add19eb7defa 81 /* Codes_SRS_SASL_PLAIN_01_019: [ message = [authzid] UTF8NUL authcid UTF8NUL passwd] */
AzureIoTClient 28:add19eb7defa 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.] */
AzureIoTClient 28:add19eb7defa 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
AzureIoTClient 28:add19eb7defa 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.] */
AzureIoTClient 28:add19eb7defa 86 if (authzid_length > 0)
AzureIoTClient 28:add19eb7defa 87 {
AzureIoTClient 28:add19eb7defa 88 (void)memcpy(result->init_bytes, sasl_plain_config->authzid, authzid_length);
AzureIoTClient 28:add19eb7defa 89 }
Azure.IoT Build 0:6ae2f7bca550 90
AzureIoTClient 28:add19eb7defa 91 result->init_bytes[authzid_length] = 0;
AzureIoTClient 28:add19eb7defa 92 (void)memcpy(result->init_bytes + authzid_length + 1, sasl_plain_config->authcid, authcid_length);
AzureIoTClient 28:add19eb7defa 93 result->init_bytes[authzid_length + authcid_length + 1] = 0;
AzureIoTClient 28:add19eb7defa 94 (void)memcpy(result->init_bytes + authzid_length + authcid_length + 2, sasl_plain_config->passwd, passwd_length);
AzureIoTClient 28:add19eb7defa 95 result->init_bytes_length = (uint32_t)(authzid_length + authcid_length + passwd_length + 2);
AzureIoTClient 28:add19eb7defa 96 }
AzureIoTClient 28:add19eb7defa 97 }
AzureIoTClient 28:add19eb7defa 98 }
AzureIoTClient 28:add19eb7defa 99 }
AzureIoTClient 28:add19eb7defa 100 }
Azure.IoT Build 0:6ae2f7bca550 101
AzureIoTClient 28:add19eb7defa 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 28:add19eb7defa 109 /* Codes_SRS_SASL_PLAIN_01_006: [If the argument `concrete_sasl_mechanism` is NULL, `saslplain_destroy` shall do nothing.] */
AzureIoTClient 28:add19eb7defa 110 LogError("NULL sasl_mechanism_concrete_handle");
AzureIoTClient 23:1111ee8bcba4 111 }
AzureIoTClient 23:1111ee8bcba4 112 else
AzureIoTClient 23:1111ee8bcba4 113 {
AzureIoTClient 28:add19eb7defa 114 /* Codes_SRS_SASL_PLAIN_01_005: [`saslplain_destroy` shall free all resources associated with the SASL mechanism.] */
AzureIoTClient 28:add19eb7defa 115 SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle;
AzureIoTClient 28:add19eb7defa 116 if (sasl_plain_instance->init_bytes != NULL)
AzureIoTClient 28:add19eb7defa 117 {
AzureIoTClient 28:add19eb7defa 118 free(sasl_plain_instance->init_bytes);
AzureIoTClient 28:add19eb7defa 119 }
Azure.IoT Build 0:6ae2f7bca550 120
AzureIoTClient 28:add19eb7defa 121 free(sasl_plain_instance);
AzureIoTClient 28:add19eb7defa 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 {
AzureIoTClient 28:add19eb7defa 127 int result;
Azure.IoT Build 0:6ae2f7bca550 128
AzureIoTClient 28:add19eb7defa 129 if ((sasl_mechanism_concrete_handle == NULL) ||
AzureIoTClient 28:add19eb7defa 130 (init_bytes == NULL))
AzureIoTClient 28:add19eb7defa 131 {
AzureIoTClient 28:add19eb7defa 132 /* Codes_SRS_SASL_PLAIN_01_009: [If any argument is NULL, `saslplain_get_init_bytes` shall return a non-zero value.] */
AzureIoTClient 28:add19eb7defa 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__;
AzureIoTClient 28:add19eb7defa 136 }
AzureIoTClient 28:add19eb7defa 137 else
AzureIoTClient 28:add19eb7defa 138 {
AzureIoTClient 28:add19eb7defa 139 SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle;
Azure.IoT Build 0:6ae2f7bca550 140
AzureIoTClient 28:add19eb7defa 141 /* Codes_SRS_SASL_PLAIN_01_007: [`saslplain_get_init_bytes` shall construct the initial bytes per the RFC 4616.] */
AzureIoTClient 28:add19eb7defa 142 init_bytes->bytes = sasl_plain_instance->init_bytes;
AzureIoTClient 28:add19eb7defa 143 init_bytes->length = sasl_plain_instance->init_bytes_length;
Azure.IoT Build 0:6ae2f7bca550 144
AzureIoTClient 28:add19eb7defa 145 /* Codes_SRS_SASL_PLAIN_01_008: [On success `saslplain_get_init_bytes` shall return zero.] */
AzureIoTClient 28:add19eb7defa 146 result = 0;
AzureIoTClient 28:add19eb7defa 147 }
Azure.IoT Build 0:6ae2f7bca550 148
AzureIoTClient 28:add19eb7defa 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 {
AzureIoTClient 28:add19eb7defa 154 const char* result;
Azure.IoT Build 0:6ae2f7bca550 155
AzureIoTClient 28:add19eb7defa 156 if (sasl_mechanism == NULL)
AzureIoTClient 28:add19eb7defa 157 {
AzureIoTClient 28:add19eb7defa 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;
AzureIoTClient 28:add19eb7defa 161 }
AzureIoTClient 28:add19eb7defa 162 else
AzureIoTClient 28:add19eb7defa 163 {
AzureIoTClient 28:add19eb7defa 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".] */
AzureIoTClient 28:add19eb7defa 165 result = "PLAIN";
AzureIoTClient 28:add19eb7defa 166 }
Azure.IoT Build 0:6ae2f7bca550 167
AzureIoTClient 28:add19eb7defa 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 {
AzureIoTClient 28:add19eb7defa 173 int result;
Azure.IoT Build 0:6ae2f7bca550 174
AzureIoTClient 28:add19eb7defa 175 (void)challenge_bytes;
Azure.IoT Build 0:6ae2f7bca550 176
AzureIoTClient 28:add19eb7defa 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.] */
AzureIoTClient 28:add19eb7defa 178 if ((concrete_sasl_mechanism == NULL) ||
AzureIoTClient 28:add19eb7defa 179 (response_bytes == NULL))
AzureIoTClient 28:add19eb7defa 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__;
AzureIoTClient 28:add19eb7defa 184 }
AzureIoTClient 28:add19eb7defa 185 else
AzureIoTClient 28:add19eb7defa 186 {
AzureIoTClient 28:add19eb7defa 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.] */
AzureIoTClient 28:add19eb7defa 188 response_bytes->bytes = NULL;
AzureIoTClient 28:add19eb7defa 189 response_bytes->length = 0;
Azure.IoT Build 0:6ae2f7bca550 190
AzureIoTClient 28:add19eb7defa 191 /* Codes_SRS_SASL_PLAIN_01_013: [On success, `saslplain_challenge` shall return 0.] */
AzureIoTClient 28:add19eb7defa 192 result = 0;
AzureIoTClient 28:add19eb7defa 193 }
Azure.IoT Build 0:6ae2f7bca550 194
AzureIoTClient 28:add19eb7defa 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 28:add19eb7defa 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 28:add19eb7defa 201 saslplain_create,
AzureIoTClient 28:add19eb7defa 202 saslplain_destroy,
AzureIoTClient 28:add19eb7defa 203 saslplain_get_init_bytes,
AzureIoTClient 28:add19eb7defa 204 saslplain_get_mechanism_name,
AzureIoTClient 28:add19eb7defa 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 {
AzureIoTClient 28:add19eb7defa 210 return &saslplain_interface;
Azure.IoT Build 0:6ae2f7bca550 211 }