A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Feb 24 14:00:58 2017 -0800
Revision:
19:000ab4e6a2c1
Parent:
17:923575db8b2d
Child:
20:206846c14c80
1.1.8

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"
Azure.IoT Build 0:6ae2f7bca550 7 #include "azure_uamqp_c/sasl_plain.h"
Azure.IoT Build 0:6ae2f7bca550 8 #include "azure_uamqp_c/amqpalloc.h"
Azure.IoT Build 0:6ae2f7bca550 9
Azure.IoT Build 0:6ae2f7bca550 10 typedef struct SASL_PLAIN_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 11 {
Azure.IoT Build 0:6ae2f7bca550 12 unsigned char* init_bytes;
AzureIoTClient 6:641a9672db08 13 uint32_t init_bytes_length;
Azure.IoT Build 0:6ae2f7bca550 14 } SASL_PLAIN_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 15
Azure.IoT Build 0:6ae2f7bca550 16 static const SASL_MECHANISM_INTERFACE_DESCRIPTION saslplain_interface =
Azure.IoT Build 0:6ae2f7bca550 17 {
Azure.IoT Build 0:6ae2f7bca550 18 /* 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 19 saslplain_create,
Azure.IoT Build 0:6ae2f7bca550 20 saslplain_destroy,
Azure.IoT Build 0:6ae2f7bca550 21 saslplain_get_init_bytes,
Azure.IoT Build 0:6ae2f7bca550 22 saslplain_get_mechanism_name,
Azure.IoT Build 0:6ae2f7bca550 23 saslplain_challenge
Azure.IoT Build 0:6ae2f7bca550 24 };
Azure.IoT Build 0:6ae2f7bca550 25
Azure.IoT Build 0:6ae2f7bca550 26 CONCRETE_SASL_MECHANISM_HANDLE saslplain_create(void* config)
Azure.IoT Build 0:6ae2f7bca550 27 {
Azure.IoT Build 0:6ae2f7bca550 28 SASL_PLAIN_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 29
Azure.IoT Build 0:6ae2f7bca550 30 if (config == NULL)
Azure.IoT Build 0:6ae2f7bca550 31 {
Azure.IoT Build 0:6ae2f7bca550 32 /* Codes_SRS_SASL_PLAIN_01_003: [If the config argument is NULL, then saslplain_create shall fail and return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 33 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 34 }
Azure.IoT Build 0:6ae2f7bca550 35 else
Azure.IoT Build 0:6ae2f7bca550 36 {
Azure.IoT Build 0:6ae2f7bca550 37 SASL_PLAIN_CONFIG* sasl_plain_config = (SASL_PLAIN_CONFIG*)config;
Azure.IoT Build 0:6ae2f7bca550 38
Azure.IoT Build 0:6ae2f7bca550 39 /* 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 40 if ((sasl_plain_config->authcid == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 41 (sasl_plain_config->passwd == NULL))
Azure.IoT Build 0:6ae2f7bca550 42 {
Azure.IoT Build 0:6ae2f7bca550 43 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 44 }
Azure.IoT Build 0:6ae2f7bca550 45 else
Azure.IoT Build 0:6ae2f7bca550 46 {
Azure.IoT Build 0:6ae2f7bca550 47 size_t authzid_length = sasl_plain_config->authzid == NULL ? 0 : strlen(sasl_plain_config->authzid);
Azure.IoT Build 0:6ae2f7bca550 48 size_t authcid_length = strlen(sasl_plain_config->authcid);
Azure.IoT Build 0:6ae2f7bca550 49 size_t passwd_length = strlen(sasl_plain_config->passwd);
Azure.IoT Build 0:6ae2f7bca550 50
Azure.IoT Build 0:6ae2f7bca550 51 /* Codes_SRS_SASL_PLAIN_01_020: [ authcid = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 52 if ((authcid_length > 255) || (authcid_length == 0) ||
Azure.IoT Build 0:6ae2f7bca550 53 /* Codes_SRS_SASL_PLAIN_01_021: [ authzid = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 54 (authzid_length > 255) ||
Azure.IoT Build 0:6ae2f7bca550 55 /* Codes_SRS_SASL_PLAIN_01_022: [ passwd = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 56 (passwd_length > 255) || (passwd_length == 0))
Azure.IoT Build 0:6ae2f7bca550 57 {
Azure.IoT Build 0:6ae2f7bca550 58 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 59 }
Azure.IoT Build 0:6ae2f7bca550 60 else
Azure.IoT Build 0:6ae2f7bca550 61 {
Azure.IoT Build 0:6ae2f7bca550 62 /* Codes_SRS_SASL_PLAIN_01_001: [saslplain_create shall return on success a non-NULL handle to a new SASL plain mechanism.] */
Azure.IoT Build 0:6ae2f7bca550 63 result = amqpalloc_malloc(sizeof(SASL_PLAIN_INSTANCE));
Azure.IoT Build 0:6ae2f7bca550 64 /* 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 65 if (result != NULL)
Azure.IoT Build 0:6ae2f7bca550 66 {
Azure.IoT Build 0:6ae2f7bca550 67 /* Ignore UTF8 for now */
Azure.IoT Build 0:6ae2f7bca550 68 result->init_bytes = (unsigned char*)amqpalloc_malloc(authzid_length + authcid_length + passwd_length + 2);
Azure.IoT Build 0:6ae2f7bca550 69 if (result->init_bytes == NULL)
Azure.IoT Build 0:6ae2f7bca550 70 {
Azure.IoT Build 0:6ae2f7bca550 71 /* 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 72 amqpalloc_free(result);
Azure.IoT Build 0:6ae2f7bca550 73 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 74 }
Azure.IoT Build 0:6ae2f7bca550 75 else
Azure.IoT Build 0:6ae2f7bca550 76 {
Azure.IoT Build 0:6ae2f7bca550 77 /* 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 78 /* 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 79 /* Codes_SRS_SASL_PLAIN_01_019: [ message = [authzid] UTF8NUL authcid UTF8NUL passwd] */
Azure.IoT Build 0:6ae2f7bca550 80 /* 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 81 /* 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 82
Azure.IoT Build 0:6ae2f7bca550 83 /* 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 84 if (authzid_length > 0)
Azure.IoT Build 0:6ae2f7bca550 85 {
Azure.IoT Build 0:6ae2f7bca550 86 (void)memcpy(result->init_bytes, sasl_plain_config->authzid, authzid_length);
Azure.IoT Build 0:6ae2f7bca550 87 }
Azure.IoT Build 0:6ae2f7bca550 88
Azure.IoT Build 0:6ae2f7bca550 89 result->init_bytes[authzid_length] = 0;
Azure.IoT Build 0:6ae2f7bca550 90 (void)memcpy(result->init_bytes + authzid_length + 1, sasl_plain_config->authcid, authcid_length);
Azure.IoT Build 0:6ae2f7bca550 91 result->init_bytes[authzid_length + authcid_length + 1] = 0;
Azure.IoT Build 0:6ae2f7bca550 92 (void)memcpy(result->init_bytes + authzid_length + authcid_length + 2, sasl_plain_config->passwd, passwd_length);
AzureIoTClient 6:641a9672db08 93 result->init_bytes_length = (uint32_t)(authzid_length + authcid_length + passwd_length + 2);
Azure.IoT Build 0:6ae2f7bca550 94 }
Azure.IoT Build 0:6ae2f7bca550 95 }
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 return result;
Azure.IoT Build 0:6ae2f7bca550 101 }
Azure.IoT Build 0:6ae2f7bca550 102
Azure.IoT Build 0:6ae2f7bca550 103 void saslplain_destroy(CONCRETE_SASL_MECHANISM_HANDLE sasl_mechanism_concrete_handle)
Azure.IoT Build 0:6ae2f7bca550 104 {
Azure.IoT Build 0:6ae2f7bca550 105 if (sasl_mechanism_concrete_handle != NULL)
Azure.IoT Build 0:6ae2f7bca550 106 {
Azure.IoT Build 0:6ae2f7bca550 107 /* Codes_SRS_SASL_PLAIN_01_005: [saslplain_destroy shall free all resources associated with the SASL mechanism.] */
Azure.IoT Build 0:6ae2f7bca550 108 SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle;
Azure.IoT Build 0:6ae2f7bca550 109 if (sasl_plain_instance->init_bytes != NULL)
Azure.IoT Build 0:6ae2f7bca550 110 {
Azure.IoT Build 0:6ae2f7bca550 111 amqpalloc_free(sasl_plain_instance->init_bytes);
Azure.IoT Build 0:6ae2f7bca550 112 }
Azure.IoT Build 0:6ae2f7bca550 113
Azure.IoT Build 0:6ae2f7bca550 114 amqpalloc_free(sasl_plain_instance);
Azure.IoT Build 0:6ae2f7bca550 115 }
Azure.IoT Build 0:6ae2f7bca550 116 }
Azure.IoT Build 0:6ae2f7bca550 117
Azure.IoT Build 0:6ae2f7bca550 118 int saslplain_get_init_bytes(CONCRETE_SASL_MECHANISM_HANDLE sasl_mechanism_concrete_handle, SASL_MECHANISM_BYTES* init_bytes)
Azure.IoT Build 0:6ae2f7bca550 119 {
Azure.IoT Build 0:6ae2f7bca550 120 int result;
Azure.IoT Build 0:6ae2f7bca550 121
Azure.IoT Build 0:6ae2f7bca550 122 if ((sasl_mechanism_concrete_handle == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 123 (init_bytes == NULL))
Azure.IoT Build 0:6ae2f7bca550 124 {
AzureIoTClient 19:000ab4e6a2c1 125 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 126 }
Azure.IoT Build 0:6ae2f7bca550 127 else
Azure.IoT Build 0:6ae2f7bca550 128 {
Azure.IoT Build 0:6ae2f7bca550 129 SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle;
Azure.IoT Build 0:6ae2f7bca550 130
Azure.IoT Build 0:6ae2f7bca550 131 init_bytes->bytes = sasl_plain_instance->init_bytes;
Azure.IoT Build 0:6ae2f7bca550 132 init_bytes->length = sasl_plain_instance->init_bytes_length;
Azure.IoT Build 0:6ae2f7bca550 133
Azure.IoT Build 0:6ae2f7bca550 134 /* Codes_SRS_SASL_PLAIN_01_008: [On success saslplain_get_init_bytes shall return zero.] */
Azure.IoT Build 0:6ae2f7bca550 135 result = 0;
Azure.IoT Build 0:6ae2f7bca550 136 }
Azure.IoT Build 0:6ae2f7bca550 137
Azure.IoT Build 0:6ae2f7bca550 138 return result;
Azure.IoT Build 0:6ae2f7bca550 139 }
Azure.IoT Build 0:6ae2f7bca550 140
Azure.IoT Build 0:6ae2f7bca550 141 const char* saslplain_get_mechanism_name(CONCRETE_SASL_MECHANISM_HANDLE sasl_mechanism)
Azure.IoT Build 0:6ae2f7bca550 142 {
Azure.IoT Build 0:6ae2f7bca550 143 const char* result;
Azure.IoT Build 0:6ae2f7bca550 144
Azure.IoT Build 0:6ae2f7bca550 145 if (sasl_mechanism == NULL)
Azure.IoT Build 0:6ae2f7bca550 146 {
Azure.IoT Build 0:6ae2f7bca550 147 /* Codes_SRS_SASL_PLAIN_01_011: [If the argument concrete_sasl_mechanism is NULL, saslplain_get_mechanism_name shall return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 148 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 149 }
Azure.IoT Build 0:6ae2f7bca550 150 else
Azure.IoT Build 0:6ae2f7bca550 151 {
Azure.IoT Build 0:6ae2f7bca550 152 /* 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 153 result = "PLAIN";
Azure.IoT Build 0:6ae2f7bca550 154 }
Azure.IoT Build 0:6ae2f7bca550 155
Azure.IoT Build 0:6ae2f7bca550 156 return result;
Azure.IoT Build 0:6ae2f7bca550 157 }
Azure.IoT Build 0:6ae2f7bca550 158
Azure.IoT Build 0:6ae2f7bca550 159 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 160 {
Azure.IoT Build 0:6ae2f7bca550 161 int result;
Azure.IoT Build 0:6ae2f7bca550 162
Azure.IoT Build 0:6ae2f7bca550 163 (void)challenge_bytes;
Azure.IoT Build 0:6ae2f7bca550 164
Azure.IoT Build 0:6ae2f7bca550 165 /* 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 166 if ((concrete_sasl_mechanism == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 167 (response_bytes == NULL))
Azure.IoT Build 0:6ae2f7bca550 168 {
AzureIoTClient 19:000ab4e6a2c1 169 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 170 }
Azure.IoT Build 0:6ae2f7bca550 171 else
Azure.IoT Build 0:6ae2f7bca550 172 {
Azure.IoT Build 0:6ae2f7bca550 173 /* 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 174 response_bytes->bytes = NULL;
Azure.IoT Build 0:6ae2f7bca550 175 response_bytes->length = 0;
Azure.IoT Build 0:6ae2f7bca550 176
Azure.IoT Build 0:6ae2f7bca550 177 /* Codes_SRS_SASL_PLAIN_01_013: [On success, saslplain_challenge shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 178 result = 0;
Azure.IoT Build 0:6ae2f7bca550 179 }
Azure.IoT Build 0:6ae2f7bca550 180
Azure.IoT Build 0:6ae2f7bca550 181 return result;
Azure.IoT Build 0:6ae2f7bca550 182 }
Azure.IoT Build 0:6ae2f7bca550 183
Azure.IoT Build 0:6ae2f7bca550 184 const SASL_MECHANISM_INTERFACE_DESCRIPTION* saslplain_get_interface(void)
Azure.IoT Build 0:6ae2f7bca550 185 {
Azure.IoT Build 0:6ae2f7bca550 186 return &saslplain_interface;
Azure.IoT Build 0:6ae2f7bca550 187 }