A small memory footprint AMQP implimentation
Dependents: iothub_client_sample_amqp remote_monitoring simplesample_amqp
sasl_plain.c@24:2c59c2d43ebf, 2017-05-08 (annotated)
- Committer:
- AzureIoTClient
- Date:
- Mon May 08 10:50:45 2017 -0700
- Revision:
- 24:2c59c2d43ebf
- Parent:
- 23:1111ee8bcba4
- Child:
- 28:add19eb7defa
1.1.14
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 | { |
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 | CONCRETE_SASL_MECHANISM_HANDLE saslplain_create(void* config) |
Azure.IoT Build | 0:6ae2f7bca550 | 18 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 19 | SASL_PLAIN_INSTANCE* result; |
Azure.IoT Build | 0:6ae2f7bca550 | 20 | |
Azure.IoT Build | 0:6ae2f7bca550 | 21 | if (config == NULL) |
Azure.IoT Build | 0:6ae2f7bca550 | 22 | { |
AzureIoTClient | 24:2c59c2d43ebf | 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"); |
Azure.IoT Build | 0:6ae2f7bca550 | 25 | result = NULL; |
Azure.IoT Build | 0:6ae2f7bca550 | 26 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 27 | else |
Azure.IoT Build | 0:6ae2f7bca550 | 28 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 29 | SASL_PLAIN_CONFIG* sasl_plain_config = (SASL_PLAIN_CONFIG*)config; |
Azure.IoT Build | 0:6ae2f7bca550 | 30 | |
AzureIoTClient | 24:2c59c2d43ebf | 31 | /* Codes_SRS_SASL_PLAIN_01_025: [ `authzid` shall be optional. ]*/ |
Azure.IoT Build | 0:6ae2f7bca550 | 32 | if ((sasl_plain_config->authcid == NULL) || |
Azure.IoT Build | 0:6ae2f7bca550 | 33 | (sasl_plain_config->passwd == NULL)) |
Azure.IoT Build | 0:6ae2f7bca550 | 34 | { |
AzureIoTClient | 24:2c59c2d43ebf | 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 | 24:2c59c2d43ebf | 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; |
Azure.IoT Build | 0:6ae2f7bca550 | 39 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 40 | else |
Azure.IoT Build | 0:6ae2f7bca550 | 41 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 42 | size_t authzid_length = sasl_plain_config->authzid == NULL ? 0 : strlen(sasl_plain_config->authzid); |
Azure.IoT Build | 0:6ae2f7bca550 | 43 | size_t authcid_length = strlen(sasl_plain_config->authcid); |
Azure.IoT Build | 0:6ae2f7bca550 | 44 | size_t passwd_length = strlen(sasl_plain_config->passwd); |
Azure.IoT Build | 0:6ae2f7bca550 | 45 | |
Azure.IoT Build | 0:6ae2f7bca550 | 46 | /* Codes_SRS_SASL_PLAIN_01_020: [ authcid = 1*SAFE ; MUST accept up to 255 octets] */ |
Azure.IoT Build | 0:6ae2f7bca550 | 47 | if ((authcid_length > 255) || (authcid_length == 0) || |
Azure.IoT Build | 0:6ae2f7bca550 | 48 | /* Codes_SRS_SASL_PLAIN_01_021: [ authzid = 1*SAFE ; MUST accept up to 255 octets] */ |
Azure.IoT Build | 0:6ae2f7bca550 | 49 | (authzid_length > 255) || |
Azure.IoT Build | 0:6ae2f7bca550 | 50 | /* Codes_SRS_SASL_PLAIN_01_022: [ passwd = 1*SAFE ; MUST accept up to 255 octets] */ |
Azure.IoT Build | 0:6ae2f7bca550 | 51 | (passwd_length > 255) || (passwd_length == 0)) |
Azure.IoT Build | 0:6ae2f7bca550 | 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; |
Azure.IoT Build | 0:6ae2f7bca550 | 56 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 57 | else |
Azure.IoT Build | 0:6ae2f7bca550 | 58 | { |
AzureIoTClient | 24:2c59c2d43ebf | 59 | /* 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 | 60 | result = (SASL_PLAIN_INSTANCE*)malloc(sizeof(SASL_PLAIN_INSTANCE)); |
AzureIoTClient | 24:2c59c2d43ebf | 61 | if (result == NULL) |
AzureIoTClient | 24:2c59c2d43ebf | 62 | { |
AzureIoTClient | 24:2c59c2d43ebf | 63 | /* Codes_SRS_SASL_PLAIN_01_002: [If allocating the memory needed for the saslplain instance fails then `saslplain_create` shall return NULL.] */ |
AzureIoTClient | 24:2c59c2d43ebf | 64 | LogError("Cannot allocate memory for SASL plain instance"); |
AzureIoTClient | 24:2c59c2d43ebf | 65 | } |
AzureIoTClient | 24:2c59c2d43ebf | 66 | else |
Azure.IoT Build | 0:6ae2f7bca550 | 67 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 68 | /* Ignore UTF8 for now */ |
AzureIoTClient | 20:206846c14c80 | 69 | result->init_bytes = (unsigned char*)malloc(authzid_length + authcid_length + passwd_length + 2); |
Azure.IoT Build | 0:6ae2f7bca550 | 70 | if (result->init_bytes == NULL) |
Azure.IoT Build | 0:6ae2f7bca550 | 71 | { |
AzureIoTClient | 24:2c59c2d43ebf | 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); |
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); |
AzureIoTClient | 6:641a9672db08 | 95 | result->init_bytes_length = (uint32_t)(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 | { |
AzureIoTClient | 23:1111ee8bcba4 | 107 | if (sasl_mechanism_concrete_handle == NULL) |
AzureIoTClient | 23:1111ee8bcba4 | 108 | { |
AzureIoTClient | 24:2c59c2d43ebf | 109 | /* Codes_SRS_SASL_PLAIN_01_006: [If the argument `concrete_sasl_mechanism` is NULL, `saslplain_destroy` shall do nothing.] */ |
AzureIoTClient | 24:2c59c2d43ebf | 110 | LogError("NULL sasl_mechanism_concrete_handle"); |
AzureIoTClient | 23:1111ee8bcba4 | 111 | } |
AzureIoTClient | 23:1111ee8bcba4 | 112 | else |
AzureIoTClient | 23:1111ee8bcba4 | 113 | { |
AzureIoTClient | 24:2c59c2d43ebf | 114 | /* Codes_SRS_SASL_PLAIN_01_005: [`saslplain_destroy` shall free all resources associated with the SASL mechanism.] */ |
Azure.IoT Build | 0:6ae2f7bca550 | 115 | SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle; |
Azure.IoT Build | 0:6ae2f7bca550 | 116 | if (sasl_plain_instance->init_bytes != NULL) |
Azure.IoT Build | 0:6ae2f7bca550 | 117 | { |
AzureIoTClient | 20:206846c14c80 | 118 | free(sasl_plain_instance->init_bytes); |
Azure.IoT Build | 0:6ae2f7bca550 | 119 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 120 | |
AzureIoTClient | 20:206846c14c80 | 121 | free(sasl_plain_instance); |
Azure.IoT Build | 0:6ae2f7bca550 | 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 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 127 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 128 | |
Azure.IoT Build | 0:6ae2f7bca550 | 129 | if ((sasl_mechanism_concrete_handle == NULL) || |
Azure.IoT Build | 0:6ae2f7bca550 | 130 | (init_bytes == NULL)) |
Azure.IoT Build | 0:6ae2f7bca550 | 131 | { |
AzureIoTClient | 24:2c59c2d43ebf | 132 | /* Codes_SRS_SASL_PLAIN_01_009: [If any argument is NULL, `saslplain_get_init_bytes` shall return a non-zero value.] */ |
AzureIoTClient | 24:2c59c2d43ebf | 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__; |
Azure.IoT Build | 0:6ae2f7bca550 | 136 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 137 | else |
Azure.IoT Build | 0:6ae2f7bca550 | 138 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 139 | SASL_PLAIN_INSTANCE* sasl_plain_instance = (SASL_PLAIN_INSTANCE*)sasl_mechanism_concrete_handle; |
Azure.IoT Build | 0:6ae2f7bca550 | 140 | |
AzureIoTClient | 24:2c59c2d43ebf | 141 | /* Codes_SRS_SASL_PLAIN_01_007: [`saslplain_get_init_bytes` shall construct the initial bytes per the RFC 4616.] */ |
Azure.IoT Build | 0:6ae2f7bca550 | 142 | init_bytes->bytes = sasl_plain_instance->init_bytes; |
Azure.IoT Build | 0:6ae2f7bca550 | 143 | init_bytes->length = sasl_plain_instance->init_bytes_length; |
Azure.IoT Build | 0:6ae2f7bca550 | 144 | |
AzureIoTClient | 24:2c59c2d43ebf | 145 | /* Codes_SRS_SASL_PLAIN_01_008: [On success `saslplain_get_init_bytes` shall return zero.] */ |
Azure.IoT Build | 0:6ae2f7bca550 | 146 | result = 0; |
Azure.IoT Build | 0:6ae2f7bca550 | 147 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 148 | |
Azure.IoT Build | 0:6ae2f7bca550 | 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 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 154 | const char* result; |
Azure.IoT Build | 0:6ae2f7bca550 | 155 | |
Azure.IoT Build | 0:6ae2f7bca550 | 156 | if (sasl_mechanism == NULL) |
Azure.IoT Build | 0:6ae2f7bca550 | 157 | { |
AzureIoTClient | 24:2c59c2d43ebf | 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; |
Azure.IoT Build | 0:6ae2f7bca550 | 161 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 162 | else |
Azure.IoT Build | 0:6ae2f7bca550 | 163 | { |
AzureIoTClient | 24:2c59c2d43ebf | 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".] */ |
Azure.IoT Build | 0:6ae2f7bca550 | 165 | result = "PLAIN"; |
Azure.IoT Build | 0:6ae2f7bca550 | 166 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 167 | |
Azure.IoT Build | 0:6ae2f7bca550 | 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 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 173 | int result; |
Azure.IoT Build | 0:6ae2f7bca550 | 174 | |
Azure.IoT Build | 0:6ae2f7bca550 | 175 | (void)challenge_bytes; |
Azure.IoT Build | 0:6ae2f7bca550 | 176 | |
AzureIoTClient | 24:2c59c2d43ebf | 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.] */ |
Azure.IoT Build | 0:6ae2f7bca550 | 178 | if ((concrete_sasl_mechanism == NULL) || |
Azure.IoT Build | 0:6ae2f7bca550 | 179 | (response_bytes == NULL)) |
Azure.IoT Build | 0:6ae2f7bca550 | 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__; |
Azure.IoT Build | 0:6ae2f7bca550 | 184 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 185 | else |
Azure.IoT Build | 0:6ae2f7bca550 | 186 | { |
AzureIoTClient | 24:2c59c2d43ebf | 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.] */ |
Azure.IoT Build | 0:6ae2f7bca550 | 188 | response_bytes->bytes = NULL; |
Azure.IoT Build | 0:6ae2f7bca550 | 189 | response_bytes->length = 0; |
Azure.IoT Build | 0:6ae2f7bca550 | 190 | |
AzureIoTClient | 24:2c59c2d43ebf | 191 | /* Codes_SRS_SASL_PLAIN_01_013: [On success, `saslplain_challenge` shall return 0.] */ |
Azure.IoT Build | 0:6ae2f7bca550 | 192 | result = 0; |
Azure.IoT Build | 0:6ae2f7bca550 | 193 | } |
Azure.IoT Build | 0:6ae2f7bca550 | 194 | |
Azure.IoT Build | 0:6ae2f7bca550 | 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 | 24:2c59c2d43ebf | 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 | 24:2c59c2d43ebf | 201 | saslplain_create, |
AzureIoTClient | 24:2c59c2d43ebf | 202 | saslplain_destroy, |
AzureIoTClient | 24:2c59c2d43ebf | 203 | saslplain_get_init_bytes, |
AzureIoTClient | 24:2c59c2d43ebf | 204 | saslplain_get_mechanism_name, |
AzureIoTClient | 24:2c59c2d43ebf | 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 | { |
Azure.IoT Build | 0:6ae2f7bca550 | 210 | return &saslplain_interface; |
Azure.IoT Build | 0:6ae2f7bca550 | 211 | } |