A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Apr 21 14:50:32 2017 -0700
Revision:
23:1111ee8bcba4
Parent:
20:206846c14c80
Child:
24:2c59c2d43ebf
1.1.13

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 static const SASL_MECHANISM_INTERFACE_DESCRIPTION saslplain_interface =
Azure.IoT Build 0:6ae2f7bca550 18 {
Azure.IoT Build 0:6ae2f7bca550 19 /* 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.] */
Azure.IoT Build 0:6ae2f7bca550 20 saslplain_create,
Azure.IoT Build 0:6ae2f7bca550 21 saslplain_destroy,
Azure.IoT Build 0:6ae2f7bca550 22 saslplain_get_init_bytes,
Azure.IoT Build 0:6ae2f7bca550 23 saslplain_get_mechanism_name,
Azure.IoT Build 0:6ae2f7bca550 24 saslplain_challenge
Azure.IoT Build 0:6ae2f7bca550 25 };
Azure.IoT Build 0:6ae2f7bca550 26
Azure.IoT Build 0:6ae2f7bca550 27 CONCRETE_SASL_MECHANISM_HANDLE saslplain_create(void* config)
Azure.IoT Build 0:6ae2f7bca550 28 {
Azure.IoT Build 0:6ae2f7bca550 29 SASL_PLAIN_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 30
Azure.IoT Build 0:6ae2f7bca550 31 if (config == NULL)
Azure.IoT Build 0:6ae2f7bca550 32 {
Azure.IoT Build 0:6ae2f7bca550 33 /* Codes_SRS_SASL_PLAIN_01_003: [If the config argument is NULL, then saslplain_create shall fail and return NULL.] */
AzureIoTClient 23:1111ee8bcba4 34 LogError("NULL config");
Azure.IoT Build 0:6ae2f7bca550 35 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 36 }
Azure.IoT Build 0:6ae2f7bca550 37 else
Azure.IoT Build 0:6ae2f7bca550 38 {
Azure.IoT Build 0:6ae2f7bca550 39 SASL_PLAIN_CONFIG* sasl_plain_config = (SASL_PLAIN_CONFIG*)config;
Azure.IoT Build 0:6ae2f7bca550 40
Azure.IoT Build 0:6ae2f7bca550 41 /* 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.] */
Azure.IoT Build 0:6ae2f7bca550 42 if ((sasl_plain_config->authcid == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 43 (sasl_plain_config->passwd == NULL))
Azure.IoT Build 0:6ae2f7bca550 44 {
AzureIoTClient 23:1111ee8bcba4 45 LogError("Bad configuration: authcid = %p, passwd = %p",
AzureIoTClient 23:1111ee8bcba4 46 sasl_plain_config->authcid, sasl_plain_config->passwd);
AzureIoTClient 23:1111ee8bcba4 47 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 48 }
Azure.IoT Build 0:6ae2f7bca550 49 else
Azure.IoT Build 0:6ae2f7bca550 50 {
Azure.IoT Build 0:6ae2f7bca550 51 size_t authzid_length = sasl_plain_config->authzid == NULL ? 0 : strlen(sasl_plain_config->authzid);
Azure.IoT Build 0:6ae2f7bca550 52 size_t authcid_length = strlen(sasl_plain_config->authcid);
Azure.IoT Build 0:6ae2f7bca550 53 size_t passwd_length = strlen(sasl_plain_config->passwd);
Azure.IoT Build 0:6ae2f7bca550 54
Azure.IoT Build 0:6ae2f7bca550 55 /* Codes_SRS_SASL_PLAIN_01_020: [ authcid = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 56 if ((authcid_length > 255) || (authcid_length == 0) ||
Azure.IoT Build 0:6ae2f7bca550 57 /* Codes_SRS_SASL_PLAIN_01_021: [ authzid = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 58 (authzid_length > 255) ||
Azure.IoT Build 0:6ae2f7bca550 59 /* Codes_SRS_SASL_PLAIN_01_022: [ passwd = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 60 (passwd_length > 255) || (passwd_length == 0))
Azure.IoT Build 0:6ae2f7bca550 61 {
AzureIoTClient 23:1111ee8bcba4 62 LogError("Bad configuration: authcid length = %u, passwd length = %u",
AzureIoTClient 23:1111ee8bcba4 63 (unsigned int)authcid_length, (unsigned int)passwd_length);
AzureIoTClient 23:1111ee8bcba4 64 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 65 }
Azure.IoT Build 0:6ae2f7bca550 66 else
Azure.IoT Build 0:6ae2f7bca550 67 {
Azure.IoT Build 0:6ae2f7bca550 68 /* 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 69 result = (SASL_PLAIN_INSTANCE*)malloc(sizeof(SASL_PLAIN_INSTANCE));
Azure.IoT Build 0:6ae2f7bca550 70 /* Codes_SRS_SASL_PLAIN_01_002: [If allocating the memory needed for the saslplain instance fails then saslplain_create shall return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 71 if (result != NULL)
Azure.IoT Build 0:6ae2f7bca550 72 {
Azure.IoT Build 0:6ae2f7bca550 73 /* Ignore UTF8 for now */
AzureIoTClient 20:206846c14c80 74 result->init_bytes = (unsigned char*)malloc(authzid_length + authcid_length + passwd_length + 2);
Azure.IoT Build 0:6ae2f7bca550 75 if (result->init_bytes == NULL)
Azure.IoT Build 0:6ae2f7bca550 76 {
Azure.IoT Build 0:6ae2f7bca550 77 /* 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 78 LogError("Cannot allocate init bytes");
AzureIoTClient 23:1111ee8bcba4 79 free(result);
Azure.IoT Build 0:6ae2f7bca550 80 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 81 }
Azure.IoT Build 0:6ae2f7bca550 82 else
Azure.IoT Build 0:6ae2f7bca550 83 {
Azure.IoT Build 0:6ae2f7bca550 84 /* 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 85 /* 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 86 /* Codes_SRS_SASL_PLAIN_01_019: [ message = [authzid] UTF8NUL authcid UTF8NUL passwd] */
Azure.IoT Build 0:6ae2f7bca550 87 /* 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 88 /* 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 89
Azure.IoT Build 0:6ae2f7bca550 90 /* 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 91 if (authzid_length > 0)
Azure.IoT Build 0:6ae2f7bca550 92 {
Azure.IoT Build 0:6ae2f7bca550 93 (void)memcpy(result->init_bytes, sasl_plain_config->authzid, authzid_length);
Azure.IoT Build 0:6ae2f7bca550 94 }
Azure.IoT Build 0:6ae2f7bca550 95
Azure.IoT Build 0:6ae2f7bca550 96 result->init_bytes[authzid_length] = 0;
Azure.IoT Build 0:6ae2f7bca550 97 (void)memcpy(result->init_bytes + authzid_length + 1, sasl_plain_config->authcid, authcid_length);
Azure.IoT Build 0:6ae2f7bca550 98 result->init_bytes[authzid_length + authcid_length + 1] = 0;
Azure.IoT Build 0:6ae2f7bca550 99 (void)memcpy(result->init_bytes + authzid_length + authcid_length + 2, sasl_plain_config->passwd, passwd_length);
AzureIoTClient 6:641a9672db08 100 result->init_bytes_length = (uint32_t)(authzid_length + authcid_length + passwd_length + 2);
Azure.IoT Build 0:6ae2f7bca550 101 }
Azure.IoT Build 0:6ae2f7bca550 102 }
Azure.IoT Build 0:6ae2f7bca550 103 }
Azure.IoT Build 0:6ae2f7bca550 104 }
Azure.IoT Build 0:6ae2f7bca550 105 }
Azure.IoT Build 0:6ae2f7bca550 106
Azure.IoT Build 0:6ae2f7bca550 107 return result;
Azure.IoT Build 0:6ae2f7bca550 108 }
Azure.IoT Build 0:6ae2f7bca550 109
Azure.IoT Build 0:6ae2f7bca550 110 void saslplain_destroy(CONCRETE_SASL_MECHANISM_HANDLE sasl_mechanism_concrete_handle)
Azure.IoT Build 0:6ae2f7bca550 111 {
AzureIoTClient 23:1111ee8bcba4 112 if (sasl_mechanism_concrete_handle == NULL)
AzureIoTClient 23:1111ee8bcba4 113 {
AzureIoTClient 23:1111ee8bcba4 114 LogError("NULL sasl_mechanism_concrete_handle");
AzureIoTClient 23:1111ee8bcba4 115 }
AzureIoTClient 23:1111ee8bcba4 116 else
AzureIoTClient 23:1111ee8bcba4 117 {
Azure.IoT Build 0:6ae2f7bca550 118 /* Codes_SRS_SASL_PLAIN_01_005: [saslplain_destroy shall free all resources associated with the SASL mechanism.] */
Azure.IoT Build 0:6ae2f7bca550 119 SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle;
Azure.IoT Build 0:6ae2f7bca550 120 if (sasl_plain_instance->init_bytes != NULL)
Azure.IoT Build 0:6ae2f7bca550 121 {
AzureIoTClient 20:206846c14c80 122 free(sasl_plain_instance->init_bytes);
Azure.IoT Build 0:6ae2f7bca550 123 }
Azure.IoT Build 0:6ae2f7bca550 124
AzureIoTClient 20:206846c14c80 125 free(sasl_plain_instance);
Azure.IoT Build 0:6ae2f7bca550 126 }
Azure.IoT Build 0:6ae2f7bca550 127 }
Azure.IoT Build 0:6ae2f7bca550 128
Azure.IoT Build 0:6ae2f7bca550 129 int saslplain_get_init_bytes(CONCRETE_SASL_MECHANISM_HANDLE sasl_mechanism_concrete_handle, SASL_MECHANISM_BYTES* init_bytes)
Azure.IoT Build 0:6ae2f7bca550 130 {
Azure.IoT Build 0:6ae2f7bca550 131 int result;
Azure.IoT Build 0:6ae2f7bca550 132
Azure.IoT Build 0:6ae2f7bca550 133 if ((sasl_mechanism_concrete_handle == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 134 (init_bytes == NULL))
Azure.IoT Build 0:6ae2f7bca550 135 {
AzureIoTClient 23:1111ee8bcba4 136 LogError("Bad arguments: sasl_mechanism_concrete_handle = %p, init_bytes = %p",
AzureIoTClient 23:1111ee8bcba4 137 sasl_mechanism_concrete_handle, init_bytes);
AzureIoTClient 23:1111ee8bcba4 138 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 139 }
Azure.IoT Build 0:6ae2f7bca550 140 else
Azure.IoT Build 0:6ae2f7bca550 141 {
Azure.IoT Build 0:6ae2f7bca550 142 SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle;
Azure.IoT Build 0:6ae2f7bca550 143
Azure.IoT Build 0:6ae2f7bca550 144 init_bytes->bytes = sasl_plain_instance->init_bytes;
Azure.IoT Build 0:6ae2f7bca550 145 init_bytes->length = sasl_plain_instance->init_bytes_length;
Azure.IoT Build 0:6ae2f7bca550 146
Azure.IoT Build 0:6ae2f7bca550 147 /* Codes_SRS_SASL_PLAIN_01_008: [On success saslplain_get_init_bytes shall return zero.] */
Azure.IoT Build 0:6ae2f7bca550 148 result = 0;
Azure.IoT Build 0:6ae2f7bca550 149 }
Azure.IoT Build 0:6ae2f7bca550 150
Azure.IoT Build 0:6ae2f7bca550 151 return result;
Azure.IoT Build 0:6ae2f7bca550 152 }
Azure.IoT Build 0:6ae2f7bca550 153
Azure.IoT Build 0:6ae2f7bca550 154 const char* saslplain_get_mechanism_name(CONCRETE_SASL_MECHANISM_HANDLE sasl_mechanism)
Azure.IoT Build 0:6ae2f7bca550 155 {
Azure.IoT Build 0:6ae2f7bca550 156 const char* result;
Azure.IoT Build 0:6ae2f7bca550 157
Azure.IoT Build 0:6ae2f7bca550 158 if (sasl_mechanism == NULL)
Azure.IoT Build 0:6ae2f7bca550 159 {
Azure.IoT Build 0:6ae2f7bca550 160 /* Codes_SRS_SASL_PLAIN_01_011: [If the argument concrete_sasl_mechanism is NULL, saslplain_get_mechanism_name shall return NULL.] */
AzureIoTClient 23:1111ee8bcba4 161 LogError("NULL sasl_mechanism");
AzureIoTClient 23:1111ee8bcba4 162 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 163 }
Azure.IoT Build 0:6ae2f7bca550 164 else
Azure.IoT Build 0:6ae2f7bca550 165 {
Azure.IoT Build 0:6ae2f7bca550 166 /* 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 167 result = "PLAIN";
Azure.IoT Build 0:6ae2f7bca550 168 }
Azure.IoT Build 0:6ae2f7bca550 169
Azure.IoT Build 0:6ae2f7bca550 170 return result;
Azure.IoT Build 0:6ae2f7bca550 171 }
Azure.IoT Build 0:6ae2f7bca550 172
Azure.IoT Build 0:6ae2f7bca550 173 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 174 {
Azure.IoT Build 0:6ae2f7bca550 175 int result;
Azure.IoT Build 0:6ae2f7bca550 176
Azure.IoT Build 0:6ae2f7bca550 177 (void)challenge_bytes;
Azure.IoT Build 0:6ae2f7bca550 178
Azure.IoT Build 0:6ae2f7bca550 179 /* 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 180 if ((concrete_sasl_mechanism == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 181 (response_bytes == NULL))
Azure.IoT Build 0:6ae2f7bca550 182 {
AzureIoTClient 23:1111ee8bcba4 183 LogError("Bad arguments: concrete_sasl_mechanism = %p, response_bytes = %p",
AzureIoTClient 23:1111ee8bcba4 184 concrete_sasl_mechanism, response_bytes);
AzureIoTClient 23:1111ee8bcba4 185 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 186 }
Azure.IoT Build 0:6ae2f7bca550 187 else
Azure.IoT Build 0:6ae2f7bca550 188 {
Azure.IoT Build 0:6ae2f7bca550 189 /* 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 190 response_bytes->bytes = NULL;
Azure.IoT Build 0:6ae2f7bca550 191 response_bytes->length = 0;
Azure.IoT Build 0:6ae2f7bca550 192
Azure.IoT Build 0:6ae2f7bca550 193 /* Codes_SRS_SASL_PLAIN_01_013: [On success, saslplain_challenge shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 194 result = 0;
Azure.IoT Build 0:6ae2f7bca550 195 }
Azure.IoT Build 0:6ae2f7bca550 196
Azure.IoT Build 0:6ae2f7bca550 197 return result;
Azure.IoT Build 0:6ae2f7bca550 198 }
Azure.IoT Build 0:6ae2f7bca550 199
Azure.IoT Build 0:6ae2f7bca550 200 const SASL_MECHANISM_INTERFACE_DESCRIPTION* saslplain_get_interface(void)
Azure.IoT Build 0:6ae2f7bca550 201 {
Azure.IoT Build 0:6ae2f7bca550 202 return &saslplain_interface;
Azure.IoT Build 0:6ae2f7bca550 203 }