Skip to content
This repository has been archived by the owner on Sep 4, 2024. It is now read-only.

Commit

Permalink
Add a simple C example
Browse files Browse the repository at this point in the history
Signed-off-by: David Mulder <[email protected]>
  • Loading branch information
dmulder committed May 31, 2024
1 parent ca5bfd1 commit 2c21375
Show file tree
Hide file tree
Showing 3 changed files with 207 additions and 0 deletions.
1 change: 1 addition & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
msal_example
5 changes: 5 additions & 0 deletions example/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
all:
gcc -o msal_example msal_example.c -I../target/debug/include -L../target/debug -lmsal

run:
LD_LIBRARY_PATH=../target/debug ./msal_example
201 changes: 201 additions & 0 deletions example/msal_example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
Unix Azure Entra ID implementation
Copyright (C) David Mulder <[email protected]> 2024
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <msal.h>
#include <string.h>
#include <unistd.h>

void strip_newline(char *str) {
int len = strlen(str);
if (str[len-1] == '\n') {
str[len-1] = '\0';
}
}

int main() {
BoxedDynTpm *tpm = NULL;
BrokerClientApplication *client = NULL;
LoadableMachineKey *loadable_machine_key = NULL;
MachineKey *machine_key = NULL;
EnrollAttrs *attrs = NULL;
MFAAuthContinue *flow = NULL;
UserToken *token = NULL;
LoadableMsOapxbcRsaKey *transport_key = NULL;
LoadableIdentityKey *cert_key = NULL;
MSAL_ERROR err;
char* auth_value = NULL;
char *domain = NULL;
size_t len;
char *username = NULL;
char *password = NULL;
char *msg = NULL;
char *mfa_method = NULL;
char *device_id = NULL;
bool user_exists;

err = tpm_init(NULL, &tpm);
if (err != SUCCESS) {
printf("Failed to initialize tpm!\n");
goto OUT;
}
auth_value_generate(&auth_value);
printf("auth_value: %s\n", auth_value);

err = tpm_machine_key_create(tpm, auth_value, &loadable_machine_key);
if (err != SUCCESS) {
printf("Failed to create loadable machine key!\n");
goto OUT;
}

err = tpm_machine_key_load(tpm,
auth_value,
loadable_machine_key,
&machine_key);
if (err != SUCCESS) {
printf("Failed to load machine key!\n");
goto OUT;
}

err = broker_init(NULL, NULL, NULL, &client);
if (err != SUCCESS) {
printf("Failed to initialize the broker!\n");
goto OUT;
}

printf("Enter a domain name: ");
getline(&domain, &len, stdin);
strip_newline(domain);

printf("Please enter your EntraID username: ");
getline(&username, &len, stdin);
strip_newline(username);

err = broker_check_user_exists(client, username, &user_exists);
if (err != SUCCESS) {
printf("Failed to check if the user exists!\n");
goto OUT;
}
if (user_exists) {
printf("User %s exists!\n", username);
} else {
printf("User %s does not exist!\n", username);
goto OUT;
}

password = getpass("Password: ");

err = broker_initiate_acquire_token_by_mfa_flow_for_device_enrollment(client,
username,
password,
&flow);
if (err != SUCCESS) {
printf("Failed to initiate an mfa token acquire!\n");
goto OUT;
}

err = mfa_auth_continue_msg(flow, &msg);
if (err != SUCCESS) {
printf("Failed to fetch MFA auth message!\n");
goto OUT;
}
printf("%s", msg);
fflush(stdout);

err = mfa_auth_continue_mfa_method(flow, &mfa_method);
if (err != SUCCESS) {
printf("Failed to fetch MFA method!\n");
goto OUT;
}
if (strcmp(mfa_method, "PhoneAppOTP") == 0
|| strcmp(mfa_method, "OneWaySMS") == 0
|| strcmp(mfa_method, "ConsolidatedTelephony") == 0) {
char *otp = getpass("");
err = broker_acquire_token_by_mfa_flow(client,
username,
otp,
0,
flow,
&token);
if (err != SUCCESS) {
printf("Failed to authenticate with otp!\n");
free(otp);
goto OUT;
}
free(otp);
} else {
int polling_interval = mfa_auth_continue_polling_interval(flow);
int max_poll_attempts = mfa_auth_continue_max_poll_attempts(flow);
for (int i = 0; i < max_poll_attempts; i++) {
err = broker_acquire_token_by_mfa_flow(client,
username,
NULL,
i,
flow,
&token);
if (err == MFA_POLL_CONTINUE) {
sleep(polling_interval/1000);
} else {
printf("Failed to authenticate when polling!\n");
break;
}
}
}
printf("Authentication was successful!\n");

err = enroll_attrs_init(domain,
"msal_example_c",
NULL,
0,
NULL,
&attrs);
if (err != SUCCESS) {
printf("Failed to create enrollment attributes!\n");
}

err = broker_enroll_device(client,
token,
attrs,
tpm,
machine_key,
&transport_key,
&cert_key,
&device_id);
if (err != SUCCESS) {
printf("Failed to enroll the device!\n");
goto OUT;
}
printf("Enrolled with device id: %s\n", device_id);

OUT:
user_token_free(token);
mfa_auth_continue_free(flow);
string_free(auth_value);
loadable_machine_key_free(loadable_machine_key);
machine_key_free(machine_key);
broker_free(client);
tpm_free(tpm);
free(username);
free(domain);
free(password);
string_free(msg);
string_free(mfa_method);
string_free(device_id);
loadable_ms_oapxbc_rsa_key_free(transport_key);
loadable_identity_key_free(cert_key);
}

0 comments on commit 2c21375

Please sign in to comment.