A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

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