A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
Azure.IoT Build
Date:
Fri Apr 08 12:01:10 2016 -0700
Revision:
0:6ae2f7bca550
Child:
6:641a9672db08
1.0.4

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 #ifdef _CRTDBG_MAP_ALLOC
Azure.IoT Build 0:6ae2f7bca550 6 #include <crtdbg.h>
Azure.IoT Build 0:6ae2f7bca550 7 #endif
Azure.IoT Build 0:6ae2f7bca550 8 #include <string.h>
Azure.IoT Build 0:6ae2f7bca550 9 #include "azure_uamqp_c/sasl_plain.h"
Azure.IoT Build 0:6ae2f7bca550 10 #include "azure_uamqp_c/amqpalloc.h"
Azure.IoT Build 0:6ae2f7bca550 11
Azure.IoT Build 0:6ae2f7bca550 12 typedef struct SASL_PLAIN_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 13 {
Azure.IoT Build 0:6ae2f7bca550 14 unsigned char* init_bytes;
Azure.IoT Build 0:6ae2f7bca550 15 size_t init_bytes_length;
Azure.IoT Build 0:6ae2f7bca550 16 } SASL_PLAIN_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 17
Azure.IoT Build 0:6ae2f7bca550 18 static const SASL_MECHANISM_INTERFACE_DESCRIPTION saslplain_interface =
Azure.IoT Build 0:6ae2f7bca550 19 {
Azure.IoT Build 0:6ae2f7bca550 20 /* 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 21 saslplain_create,
Azure.IoT Build 0:6ae2f7bca550 22 saslplain_destroy,
Azure.IoT Build 0:6ae2f7bca550 23 saslplain_get_init_bytes,
Azure.IoT Build 0:6ae2f7bca550 24 saslplain_get_mechanism_name,
Azure.IoT Build 0:6ae2f7bca550 25 saslplain_challenge
Azure.IoT Build 0:6ae2f7bca550 26 };
Azure.IoT Build 0:6ae2f7bca550 27
Azure.IoT Build 0:6ae2f7bca550 28 CONCRETE_SASL_MECHANISM_HANDLE saslplain_create(void* config)
Azure.IoT Build 0:6ae2f7bca550 29 {
Azure.IoT Build 0:6ae2f7bca550 30 SASL_PLAIN_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 31
Azure.IoT Build 0:6ae2f7bca550 32 if (config == NULL)
Azure.IoT Build 0:6ae2f7bca550 33 {
Azure.IoT Build 0:6ae2f7bca550 34 /* 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 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 {
Azure.IoT Build 0:6ae2f7bca550 45 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 46 }
Azure.IoT Build 0:6ae2f7bca550 47 else
Azure.IoT Build 0:6ae2f7bca550 48 {
Azure.IoT Build 0:6ae2f7bca550 49 size_t authzid_length = sasl_plain_config->authzid == NULL ? 0 : strlen(sasl_plain_config->authzid);
Azure.IoT Build 0:6ae2f7bca550 50 size_t authcid_length = strlen(sasl_plain_config->authcid);
Azure.IoT Build 0:6ae2f7bca550 51 size_t passwd_length = strlen(sasl_plain_config->passwd);
Azure.IoT Build 0:6ae2f7bca550 52
Azure.IoT Build 0:6ae2f7bca550 53 /* Codes_SRS_SASL_PLAIN_01_020: [ authcid = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 54 if ((authcid_length > 255) || (authcid_length == 0) ||
Azure.IoT Build 0:6ae2f7bca550 55 /* Codes_SRS_SASL_PLAIN_01_021: [ authzid = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 56 (authzid_length > 255) ||
Azure.IoT Build 0:6ae2f7bca550 57 /* Codes_SRS_SASL_PLAIN_01_022: [ passwd = 1*SAFE ; MUST accept up to 255 octets] */
Azure.IoT Build 0:6ae2f7bca550 58 (passwd_length > 255) || (passwd_length == 0))
Azure.IoT Build 0:6ae2f7bca550 59 {
Azure.IoT Build 0:6ae2f7bca550 60 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 61 }
Azure.IoT Build 0:6ae2f7bca550 62 else
Azure.IoT Build 0:6ae2f7bca550 63 {
Azure.IoT Build 0:6ae2f7bca550 64 /* 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 65 result = amqpalloc_malloc(sizeof(SASL_PLAIN_INSTANCE));
Azure.IoT Build 0:6ae2f7bca550 66 /* 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 67 if (result != NULL)
Azure.IoT Build 0:6ae2f7bca550 68 {
Azure.IoT Build 0:6ae2f7bca550 69 /* Ignore UTF8 for now */
Azure.IoT Build 0:6ae2f7bca550 70 result->init_bytes = (unsigned char*)amqpalloc_malloc(authzid_length + authcid_length + passwd_length + 2);
Azure.IoT Build 0:6ae2f7bca550 71 if (result->init_bytes == NULL)
Azure.IoT Build 0:6ae2f7bca550 72 {
Azure.IoT Build 0:6ae2f7bca550 73 /* 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 74 amqpalloc_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);
Azure.IoT Build 0:6ae2f7bca550 95 result->init_bytes_length = 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 {
Azure.IoT Build 0:6ae2f7bca550 107 if (sasl_mechanism_concrete_handle != NULL)
Azure.IoT Build 0:6ae2f7bca550 108 {
Azure.IoT Build 0:6ae2f7bca550 109 /* Codes_SRS_SASL_PLAIN_01_005: [saslplain_destroy shall free all resources associated with the SASL mechanism.] */
Azure.IoT Build 0:6ae2f7bca550 110 SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle;
Azure.IoT Build 0:6ae2f7bca550 111 if (sasl_plain_instance->init_bytes != NULL)
Azure.IoT Build 0:6ae2f7bca550 112 {
Azure.IoT Build 0:6ae2f7bca550 113 amqpalloc_free(sasl_plain_instance->init_bytes);
Azure.IoT Build 0:6ae2f7bca550 114 }
Azure.IoT Build 0:6ae2f7bca550 115
Azure.IoT Build 0:6ae2f7bca550 116 amqpalloc_free(sasl_plain_instance);
Azure.IoT Build 0:6ae2f7bca550 117 }
Azure.IoT Build 0:6ae2f7bca550 118 }
Azure.IoT Build 0:6ae2f7bca550 119
Azure.IoT Build 0:6ae2f7bca550 120 int saslplain_get_init_bytes(CONCRETE_SASL_MECHANISM_HANDLE sasl_mechanism_concrete_handle, SASL_MECHANISM_BYTES* init_bytes)
Azure.IoT Build 0:6ae2f7bca550 121 {
Azure.IoT Build 0:6ae2f7bca550 122 int result;
Azure.IoT Build 0:6ae2f7bca550 123
Azure.IoT Build 0:6ae2f7bca550 124 if ((sasl_mechanism_concrete_handle == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 125 (init_bytes == NULL))
Azure.IoT Build 0:6ae2f7bca550 126 {
Azure.IoT Build 0:6ae2f7bca550 127 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 128 }
Azure.IoT Build 0:6ae2f7bca550 129 else
Azure.IoT Build 0:6ae2f7bca550 130 {
Azure.IoT Build 0:6ae2f7bca550 131 SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle;
Azure.IoT Build 0:6ae2f7bca550 132
Azure.IoT Build 0:6ae2f7bca550 133 init_bytes->bytes = sasl_plain_instance->init_bytes;
Azure.IoT Build 0:6ae2f7bca550 134 init_bytes->length = sasl_plain_instance->init_bytes_length;
Azure.IoT Build 0:6ae2f7bca550 135
Azure.IoT Build 0:6ae2f7bca550 136 /* Codes_SRS_SASL_PLAIN_01_008: [On success saslplain_get_init_bytes shall return zero.] */
Azure.IoT Build 0:6ae2f7bca550 137 result = 0;
Azure.IoT Build 0:6ae2f7bca550 138 }
Azure.IoT Build 0:6ae2f7bca550 139
Azure.IoT Build 0:6ae2f7bca550 140 return result;
Azure.IoT Build 0:6ae2f7bca550 141 }
Azure.IoT Build 0:6ae2f7bca550 142
Azure.IoT Build 0:6ae2f7bca550 143 const char* saslplain_get_mechanism_name(CONCRETE_SASL_MECHANISM_HANDLE sasl_mechanism)
Azure.IoT Build 0:6ae2f7bca550 144 {
Azure.IoT Build 0:6ae2f7bca550 145 const char* result;
Azure.IoT Build 0:6ae2f7bca550 146
Azure.IoT Build 0:6ae2f7bca550 147 if (sasl_mechanism == NULL)
Azure.IoT Build 0:6ae2f7bca550 148 {
Azure.IoT Build 0:6ae2f7bca550 149 /* 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 150 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 151 }
Azure.IoT Build 0:6ae2f7bca550 152 else
Azure.IoT Build 0:6ae2f7bca550 153 {
Azure.IoT Build 0:6ae2f7bca550 154 /* 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 155 result = "PLAIN";
Azure.IoT Build 0:6ae2f7bca550 156 }
Azure.IoT Build 0:6ae2f7bca550 157
Azure.IoT Build 0:6ae2f7bca550 158 return result;
Azure.IoT Build 0:6ae2f7bca550 159 }
Azure.IoT Build 0:6ae2f7bca550 160
Azure.IoT Build 0:6ae2f7bca550 161 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 162 {
Azure.IoT Build 0:6ae2f7bca550 163 int result;
Azure.IoT Build 0:6ae2f7bca550 164
Azure.IoT Build 0:6ae2f7bca550 165 (void)challenge_bytes;
Azure.IoT Build 0:6ae2f7bca550 166
Azure.IoT Build 0:6ae2f7bca550 167 /* 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 168 if ((concrete_sasl_mechanism == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 169 (response_bytes == NULL))
Azure.IoT Build 0:6ae2f7bca550 170 {
Azure.IoT Build 0:6ae2f7bca550 171 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 172 }
Azure.IoT Build 0:6ae2f7bca550 173 else
Azure.IoT Build 0:6ae2f7bca550 174 {
Azure.IoT Build 0:6ae2f7bca550 175 /* 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 176 response_bytes->bytes = NULL;
Azure.IoT Build 0:6ae2f7bca550 177 response_bytes->length = 0;
Azure.IoT Build 0:6ae2f7bca550 178
Azure.IoT Build 0:6ae2f7bca550 179 /* Codes_SRS_SASL_PLAIN_01_013: [On success, saslplain_challenge shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 180 result = 0;
Azure.IoT Build 0:6ae2f7bca550 181 }
Azure.IoT Build 0:6ae2f7bca550 182
Azure.IoT Build 0:6ae2f7bca550 183 return result;
Azure.IoT Build 0:6ae2f7bca550 184 }
Azure.IoT Build 0:6ae2f7bca550 185
Azure.IoT Build 0:6ae2f7bca550 186 const SASL_MECHANISM_INTERFACE_DESCRIPTION* saslplain_get_interface(void)
Azure.IoT Build 0:6ae2f7bca550 187 {
Azure.IoT Build 0:6ae2f7bca550 188 return &saslplain_interface;
Azure.IoT Build 0:6ae2f7bca550 189 }