A small memory footprint AMQP implimentation
Dependents: iothub_client_sample_amqp remote_monitoring simplesample_amqp
sasl_plain.c@28:add19eb7defa, 2017-06-30 (annotated)
- 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?
User | Revision | Line number | New 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 | } |