Skip to content

Commit

Permalink
Merge pull request #240 from openziti/mfa
Browse files Browse the repository at this point in the history
inital mfa
  • Loading branch information
andrewpmartinez authored Mar 25, 2021
2 parents ec61891 + c28b9a7 commit 6c97311
Show file tree
Hide file tree
Showing 14 changed files with 774 additions and 50 deletions.
45 changes: 45 additions & 0 deletions inc_internal/auth_queries.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
Copyright (c) 2020 Netfoundry, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef ZITI_SDK_AUTH_QUERIES_H
#define ZITI_SDK_AUTH_QUERIES_H

#include <uv.h>
#include "zt_internal.h"

#ifdef __cplusplus
extern "C" {
#endif

#include "zt_internal.h"
#include <utils.h>

struct auth_queries {
bool outstanding_auth_queries;
bool awaiting_mfa_cb;
};

extern void ziti_auth_query_init(struct ziti_ctx *ztx);
extern void ziti_auth_query_free(struct auth_queries* aq);

void ziti_auth_query_process(ziti_context ztx, void(*cb)(ziti_context ztx));

#ifdef __cplusplus
}
#endif


#endif //ZITI_SDK_AUTH_QUERIES_H
13 changes: 12 additions & 1 deletion inc_internal/internal_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ XX(token, string, none, token, __VA_ARGS__) \
XX(expires, timestamp, ptr, expiresAt, __VA_ARGS__) \
XX(updated, timestamp, ptr, updatedAt, __VA_ARGS__) \
XX(identity, ziti_identity, ptr, identity, __VA_ARGS__) \
XX(posture_query_set, ziti_posture_query_set, array, postureQueries, __VA_ARGS__)
XX(posture_query_set, ziti_posture_query_set, array, postureQueries, __VA_ARGS__) \
XX(auth_queries, ziti_auth_query_mfa, array, authQueries, __VA_ARGS__)

#define ZITI_ERROR_MODEL(XX, ...) \
XX(err, int, none, , __VA_ARGS__) \
Expand Down Expand Up @@ -115,6 +116,12 @@ XX(signers, string, array, signerFingerprints, __VA_ARGS__)
#define ZITI_SERVICE_UPDATE(XX, ...) \
XX(last_change, string, none, lastChangeAt, __VA_ARGS__)

#define ZITI_MFA_CODE_REQ(XX, ...) \
XX(code, string, none, code, __VA_ARGS__)

#define ZITI_MFA_RECOVERY_CODES_MODEL(XX, ...) \
XX(recovery_codes, string, array, recoveryCodes, __VA_ARGS__)

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -152,6 +159,10 @@ DECLARE_MODEL(ziti_pr_domain_req, ZITI_PR_DOMAIN_REQ)

DECLARE_MODEL(ziti_service_update, ZITI_SERVICE_UPDATE)

DECLARE_MODEL(ziti_mfa_code_req, ZITI_MFA_CODE_REQ)

DECLARE_MODEL(ziti_mfa_recovery_codes, ZITI_MFA_RECOVERY_CODES_MODEL)

#ifdef __cplusplus
}
#endif
Expand Down
1 change: 0 additions & 1 deletion inc_internal/posture.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ struct posture_checks {
// map<type/process_path,response>
model_map *current_responses;


// map<type/process_path, is errored
model_map *error_states;

Expand Down
18 changes: 18 additions & 0 deletions inc_internal/ziti_ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,28 @@ void ziti_ctrl_get_well_known_certs(ziti_controller *ctrl, void (*cb)(char *, zi
void ziti_ctrl_enroll(ziti_controller *ctrl, const char *method, const char *token, const char *csr,
void (*cb)(ziti_enrollment_resp *, ziti_error *, void *), void *ctx);

//Posture
void ziti_pr_post_bulk(ziti_controller *ctrl, char *body, size_t body_len, void(*cb)(void *, ziti_error *, void *), void *ctx);

void ziti_pr_post(ziti_controller *ctrl, char *body, size_t body_len,void(*cb)(void *, ziti_error *, void *), void *ctx);


//MFA
void ziti_ctrl_login_mfa(ziti_controller *ctrl, char* body, size_t body_len, void(*cb)(void *, ziti_error *, void *), void *ctx);

void ziti_ctrl_post_mfa(ziti_controller *ctrl,void(*cb)(void *, ziti_error *, void *), void *ctx);

void ziti_ctrl_get_mfa(ziti_controller *ctrl, void(*cb)(ziti_mfa_enrollment *, ziti_error *, void *), void *ctx);

void ziti_ctrl_delete_mfa(ziti_controller *ctrl, char* code, void(*cb)(void*, ziti_error *, void *), void *ctx);

void ziti_ctrl_post_mfa_verify(ziti_controller *ctrl, char* body, size_t body_len, void(*cb)(void *, ziti_error *, void *), void *ctx);

void ziti_ctrl_get_mfa_recovery_codes(ziti_controller *ctrl, char* code, void(*cb)(ziti_mfa_recovery_codes *, ziti_error *, void *), void *ctx);

void ziti_ctrl_post_mfa_recovery_codes(ziti_controller *ctrl, char* body, size_t body_len, void(*cb)(void *, ziti_error *, void *), void *ctx);


#ifdef __cplusplus
}
#endif
Expand Down
3 changes: 3 additions & 0 deletions inc_internal/zt_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ struct ziti_ctx {

/* posture check support */
struct posture_checks *posture_checks;

/* auth query (MFA) support */
struct auth_queries *auth_queries;
};

#ifdef __cplusplus
Expand Down
8 changes: 7 additions & 1 deletion includes/ziti/error_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,13 @@ limitations under the License.
/** connection was closed */ \
XX(CONN_CLOSED, "connection is closed") \
/** failed posture check */ \
XX(INVALID_POSTURE, "failed posture checek") \
XX(INVALID_POSTURE, "failed posture check") \
/** attempted to start MFA enrollment when it already has been started or completed */ \
XX(MFA_EXISTS, "an MFA enrollment already exists") \
/** attempted to use an MFA token that is invalid */ \
XX(MFA_INVALID_TOKEN, "the token provided was invalid") \
/** attempted to verify or retrieve details of an MFA enrollment that has not been completed */ \
XX(MFA_NOT_ENROLLED, "the current identity has not completed MFA enrollment") \
/** Inspired by the Android SDK: What a Terrible Failure. A condition that should never happen. */ \
XX(WTF, "WTF: programming error")

Expand Down
180 changes: 174 additions & 6 deletions includes/ziti/ziti.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,15 +208,48 @@ typedef void (*ziti_pq_process_cb)(ziti_context ztx, const char *id, const char
ziti_pr_process_cb response_cb);

/**
* \brief Ziti Event callback.
* @brief MFA authentication status callback.
*
* This callback is invoked after the ziti_ar_mfa_cb is invoked during MFA authentication.
* It should be used to observe the result of the MFA submission and to prompt the user to try
* again or give up.
*
* @see ziti_service_available(), ZITI_ERRORS
*/
typedef void (*ziti_ar_mfa_status_cb)(ziti_context ztx, void* mfa_ctx, int status, void* ctx);

/**
* @brief Callback to supply the Ziti SDK with an MFA TOTP/recovery token for authentication.
*
* The Ziti SDK caller should receive this call back when MFA authentication is required. The
* ziti_aq_mfa_cb that is registered via `ziti_options.aq_mfa_cb` will be invoked and receive
* this `ziti_ar_mfa_cb` as a callback to supply the user entered token. Additionally,
* when `ziti_ar_mfa_cb` is invoked a `ziti_ar_mfa_status_cb` may be invoked to receive the result of the code
* submission.
*/
typedef void (*ziti_ar_mfa_cb)(ziti_context ztx, void* mfa_ctx, char* code, ziti_ar_mfa_status_cb ar_mfa_status_cb, void* ctx);

/**
* @brief Auth Query for MFA authentication
*
* This callback is invoked by the Ziti SDK when an authenticating identity requires MFA.
* The callback is responsible for inspecting the authentication query, interacting with the MFA
* service, user, and invoking the provided done callback.
*
*/
typedef void (*ziti_aq_mfa_cb)(ziti_context ztx, void* mfa_ctx, ziti_auth_query_mfa *aq_mfa, ziti_ar_mfa_cb response_cb);


/**
* @brief Ziti Event callback.
*
* This callback is invoked when certain changes happen for a given ziti context.
* Subscription to events is managed by setting desired types on `ziti_options.events` field.
*
* \see ziti_event_type
* \see ziti_event_t
* \see ziti_options.event_cb
* \see ziti_options.events
* @see ziti_event_type
* @see ziti_event_t
* @see ziti_options.event_cb
* @see ziti_options.events
*/
typedef void (*ziti_event_cb)(ziti_context ztx, const ziti_event_t *event);

Expand All @@ -243,6 +276,9 @@ typedef struct ziti_options_s {
ziti_pq_process_cb pq_process_cb;
ziti_pq_domain_cb pq_domain_cb;

//mfa cbs
ziti_aq_mfa_cb aq_mfa_cb;

void *app_ctx;

/**
Expand All @@ -256,6 +292,12 @@ typedef struct ziti_options_s {
ziti_event_cb event_cb;
} ziti_options;

typedef struct ziti_init_req_s {
ziti_context ztx;
bool login;
int init_status;
} ziti_init_req;

typedef struct ziti_enroll_opts_s {
const char *jwt;
const char *enroll_key;
Expand Down Expand Up @@ -547,7 +589,7 @@ extern int ziti_shutdown(ziti_context ztx);
* @return #ZITI_OK or corresponding #ZITI_ERRORS
*/
ZITI_FUNC
int ziti_ctx_free(ziti_context *ctxp) ;
int ziti_ctx_free(ziti_context *ctxp);

/**
* @brief Shutdown Ziti Edge identity context and reclaim the memory from the provided #ziti_context.
Expand Down Expand Up @@ -782,6 +824,132 @@ extern int ziti_close_write(ziti_connection conn);
ZITI_FUNC
extern int ziti_write(ziti_connection conn, uint8_t *data, size_t length, ziti_write_cb write_cb, void *write_ctx);

/**
* @brief Callback called after ziti_mfa_enroll()
*
* This function is invoked after a call to ziti_mfa_enroll. It will contain either
* a status error or an mfa_enrollment struct that will be free'ed after the call
* back finishes.
*
* @param ztx the handle to the Ziti Edge identity context needed for other Ziti C SDK functions
* @param status an error code or #ZITI_OK
* @param mfa_enrollment contents of the mfa enrollment or NULL if status is an error
* @param ctx additional context to be passed into #ziti_mfa_enroll_cb callback
*
*/
typedef void (*ziti_mfa_enroll_cb)(ziti_context ztx, int status, ziti_mfa_enrollment *mfa_enrollment, void *ctx);

/**
* @brief Generic callback called after various MFA functions
*
*
* @param ztx the handle to the Ziti Edge identity context needed for other Ziti C SDK functions
* @param status an error code or #ZITI_OK
* @param ctx additional context to be passed into the original mfa call
*/
typedef void (*ziti_mfa_cb)(ziti_context ztx, int status, void *ctx);


/**
* @brief Callback called after ziti_mfa_get_recovery_codes() and ziti_mfa_new_recovery_codes()
*
* This function is invoked after a call to get or regenerate mfa recovery codes.
*
* @param ztx the handle to the Ziti Edge identity context needed for other Ziti C SDK functions
* @param status an error code or #ZITI_OK
* @param recovery_codes null terminated array of recovery codes
* @param ctx additional context to be passed into to the original call
*
*/
typedef void (*ziti_mfa_recovery_codes_cb)(ziti_context ztx, int status, char **recovery_codes, void *ctx);

/**
* @brief Attempts to initialize MFA enrollment
*
* Attempts to initialize enrollment. On success or failure the supplied enroll_cb
* will be called with relevant status information. The supplied ztx must be have
* passed a primary authentication mechanism (cert, updb, etc).
*
* An error status will be returned if the request fails, #ZITI_OK is expected on success.
*
* @param ztx the handle to the Ziti Edge identity context needed for other Ziti C SDK functions
* @param ziti_mfa_enroll_cb callback to receive MFA enrollment initialization status
* @param ctx additional context to be passed into the enroll_cb callback
*/
ZITI_FUNC
extern void ziti_mfa_enroll(ziti_context ztx, ziti_mfa_enroll_cb enroll_cb, void *ctx);

/**
* @brief Attempts to remove MFA
*
* Attempts to remove MFA. On success or failure the supplied remove_cb
* will be called with relevant status information. The supplied ztx must
* be fully authenticated.
*
* An error status will be returned if the request fails, #ZITI_OK is expected on success.
*
* @param ztx the handle to the Ziti Edge identity context needed for other Ziti C SDK functions
* @param code a TOTP or recovery code, may be empty string for MFA enrollments that have not completed via ziti_mfa_verify
* @param remove_cb callback to receive MFA removal status
* @param ctx additional context to be passed into the remove_cb callback
*/
ZITI_FUNC
extern void ziti_mfa_remove(ziti_context ztx, char *code, ziti_mfa_cb remove_cb, void *ctx);

/**
* @brief Attempts to verify MFA enrollment
*
* Attempts to verify MFA enrollment. On success or failure the supplied verify_cb
* will be called with relevant status information. The supplied ztx must
* be authenticated. After verification, MFA enrollment is complete.
*
* An error status will be returned if the request fails, #ZITI_OK is expected on success.
*
* @param ztx the handle to the Ziti Edge identity context needed for other Ziti C SDK functions
* @param code a valid TOTP code, must not be a recovery code
* @param remove_cb callback to receive MFA verify status
* @param ctx additional context to be passed into the verify_cb callback
*
* @return #ZITI_OK or corresponding #ZITI_ERRORS
*/
ZITI_FUNC
extern void ziti_mfa_verify(ziti_context ztx, char *code, ziti_mfa_cb verify_cb, void *ctx);


/**
* @brief Attempts to retrieve the current recovery codes for the identity
*
* Attempts to retrieve the recovery codes for the current identity. On success or failure the supplied get_cb
* will be called with relevant status information. The supplied ztx must be fully authenticated.
*
* An error status will be returned if the request fails, #ZITI_OK is expected on success.
*
* @param ztx the handle to the Ziti Edge identity context needed for other Ziti C SDK functions
* @param code a TOTP code, may be empty string for MFA enrollments that have not completed vi ziti_mfa_verify
* @param remove_cb callback to receive the result status
* @param ctx additional context to be passed into the get_cb callback
*/
ZITI_FUNC
extern void ziti_mfa_get_recovery_codes(ziti_context ztx, char *code, ziti_mfa_recovery_codes_cb get_cb, void *ctx);

/**
* @brief Attempts to generate new recovery codes and retrieve the new recovery codes for MFA
*
* Attempts to generate new recovery codes. All previous codes will become invalid and replaced with the new
* recovery codes. On success or failure the supplied get_cb will be called with relevant status information.
* The supplied ztx must be fully authenticated.
*
* An error status will be returned if the request fails, #ZITI_OK is expected on success.
*
* @param ztx the handle to the Ziti Edge identity context needed for other Ziti C SDK functions
* @param code a TOTP code
* @param new_cb callback to receive the result status
* @param ctx additional context to be passed into the get_cb callback
*/
ZITI_FUNC
extern void ziti_mfa_new_recovery_codes(ziti_context ztx, char *code, ziti_mfa_recovery_codes_cb new_cb, void *ctx);


#ifdef __cplusplus
}
#endif
Expand Down
18 changes: 18 additions & 0 deletions includes/ziti/ziti_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ limitations under the License.

#include "model_support.h"

#define ZITI_AUTH_QUERY_MFA_MODEL(XX, ...) \
XX(type_id, string, none, typeId, __VA_ARGS__) \
XX(provider, string, none, provider, __VA_ARGS__) \
XX(http_method, string, none, httpMethod, __VA_ARGS__) \
XX(http_url, string, none, httpUrl, __VA_ARGS__) \
XX(min_length, int, none, minLength, __VA_ARGS__) \
XX(max_length, int, none, maxLength, __VA_ARGS__) \
XX(format, string, none, format, __VA_ARGS__)

#define ZITI_ID_CFG_MODEL(XX, ...) \
XX(cert, string, none, cert, __VA_ARGS__) \
XX(key, string, none, key, __VA_ARGS__) \
Expand Down Expand Up @@ -92,6 +101,11 @@ XX(port, int, none, port, __VA_ARGS__) \
XX(dial_intercepted_port, bool, none, dialInterceptedPort, __VA_ARGS__) \
XX(listen_options, tag, map, listenOptions, __VA_ARGS__)

#define ZITI_MFA_ENROLLMENT_MODEL(XX, ...) \
XX(is_verified, bool, none, isVerified, __VA_ARGS__) \
XX(recovery_codes, string, array, recoveryCodes, __VA_ARGS__) \
XX(provisioning_url, string, none, provisioningUrl, __VA_ARGS__)

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -128,6 +142,10 @@ DECLARE_MODEL(ziti_server_cfg_v1, ZITI_SERVER_CFG_V1_MODEL)

DECLARE_MODEL(ziti_host_cfg_v1, ZITI_HOST_CFG_V1_MODEL)

DECLARE_MODEL(ziti_auth_query_mfa, ZITI_AUTH_QUERY_MFA_MODEL)

DECLARE_MODEL(ziti_mfa_enrollment, ZITI_MFA_ENROLLMENT_MODEL)

ZITI_FUNC const char *ziti_service_get_raw_config(ziti_service *service, const char *cfg_type);

ZITI_FUNC int ziti_service_get_config(ziti_service *service, const char *cfg_type, void *cfg,
Expand Down
Loading

0 comments on commit 6c97311

Please sign in to comment.