From a20ba0e416b48a33a88b839871fb0c7da3253a90 Mon Sep 17 00:00:00 2001 From: Philipp Eder Date: Wed, 2 Oct 2024 22:05:11 +0000 Subject: [PATCH] Adds functionality to create gss context into openvas-krb5 --- kerberos/.gitignore | 3 + kerberos/authenticate_test.c | 102 +++++------ misc/openvas-krb5.c | 341 ++++++++++++++++++++++++++++++++--- misc/openvas-krb5.h | 72 +++++++- nasl/nasl_krb5.c | 64 ++++--- 5 files changed, 468 insertions(+), 114 deletions(-) create mode 100644 kerberos/.gitignore diff --git a/kerberos/.gitignore b/kerberos/.gitignore new file mode 100644 index 000000000..bb1351e23 --- /dev/null +++ b/kerberos/.gitignore @@ -0,0 +1,3 @@ +a.out +test.sh +krb5.conf diff --git a/kerberos/authenticate_test.c b/kerberos/authenticate_test.c index f0946e32d..30ed91240 100644 --- a/kerberos/authenticate_test.c +++ b/kerberos/authenticate_test.c @@ -2,12 +2,13 @@ #include #include - +#include #define GUARD_ENV_SET(var, env) \ do \ { \ - if ((var = getenv (env)) == NULL) \ + var = okrb5_slice_from_str (getenv (env)); \ + if (var.len == 0) \ { \ fprintf (stderr, env " is not set\n"); \ return 1; \ @@ -21,69 +22,54 @@ main () char *kdc = NULL; OKrb5ErrorCode result = O_KRB5_SUCCESS; OKrb5Credential credentials; - OKrb5Element *element = NULL; - OKrb5Data *data = NULL; + OKrb5GSSContext *context = NULL; + struct OKrb5Slice from_application = {.data = NULL, .len = 0}; + struct OKrb5Slice *to_application = NULL; + bool more = false; GUARD_ENV_SET (credentials.config_path, "KRB5_CONFIG"); GUARD_ENV_SET (credentials.realm, "KRB5_REALM"); - GUARD_ENV_SET (credentials.user, "KRB5_USER"); - GUARD_ENV_SET (credentials.password, "KRB5_PASSWORD"); - if (o_krb5_find_kdc (&credentials, &kdc)) - { - GUARD_ENV_SET (kdc, "KRB5_KDC"); - if (o_krb5_add_realm (&credentials, kdc)) - { - fprintf (stderr, "Unable to add kdc\n"); - return 1; - } - } - else + GUARD_ENV_SET (credentials.user.user, "KRB5_USER"); + GUARD_ENV_SET (credentials.user.password, "KRB5_PASSWORD"); + GUARD_ENV_SET (credentials.target.host_name, "KRB5_TARGET_HOST"); + GUARD_ENV_SET (credentials.kdc, "KRB5_KDC"); + credentials.target.service = okrb5_slice_from_str ("cifs"); + memset (&credentials.target.domain, 0, sizeof (struct OKrb5Slice)); + printf ("Using realm: %s\n", (char *) credentials.realm.data); + // TODO: move to overall function + // TODO: refactor signature to use slice + // if (o_krb5_find_kdc (&credentials, &kdc)) + // { + // if (o_krb5_add_realm (&credentials, credentials.kdc.data)) + // { + // fprintf (stderr, "Unable to add kdc\n"); + // return 1; + // } + // } + // else + // { + // printf ("Using kdc: %s\n", kdc); + // free (kdc); + // } + context = okrb5_gss_init_context (); + printf ("Using realm: %s\n", (char *) credentials.realm.data); + if ((result = o_krb5_gss_prepare_context (&credentials, context))) { - printf ("Using kdc: %s\n", kdc); - free (kdc); - } - -#if OPENVAS_KRB5_CACHED != 1 - - if ((result = o_krb5_authenticate (credentials, &element))) - { - fprintf (stderr, "Error: %d: %s\n", result, - krb5_get_error_message (element->ctx, result - O_KRB5_ERROR)); - return result; - } - - printf ("Authentication Token:\n"); - printf ("--------------------\n"); - printf ("End time: %d\n", element->creds.times.endtime); - printf ("start time: %d\n", element->creds.times.starttime); - printf ("Renew till: %d\n", element->creds.times.renew_till); - if ((result = o_krb5_request (element, "test", 5, &data))) - { - fprintf (stderr, "unable to create request: %d", result); - } - if ((result = o_krb5_free_data (element, data))) - { - fprintf (stderr, "unable to free request: %d", result); + fprintf (stderr, "Unable to prepare context: %d\n", result); + return 1; } - - return 0; -#else - - if ((result = o_krb5_cache_request (credentials, "test", 5, &data))) + printf ("Using realm: %s\n", (char *) credentials.realm.data); + // first call always empty + if ((result = o_krb5_gss_update_context (context, &from_application, + &to_application, &more))) { - fprintf (stderr, "unable to create request: %d\n", result); + fprintf (stderr, "Unable to update context: %d\n", result); return 1; } - element = o_krb5_cache_find(&credentials)->element; - if (element == NULL) + printf ("success: %d: outdata_len: %zu\n", result, to_application->len); + + for (size_t i = 0; i < to_application->len; i++) { - fprintf (stderr, "element not found: %d", result); - return 1; + printf ("%02x", ((char *) to_application->data)[i]); } - printf ("Authentication Token:\n"); - printf ("--------------------\n"); - printf ("End time: %d\n", element->creds.times.endtime); - printf ("start time: %d\n", element->creds.times.starttime); - printf ("Renew till: %d\n", element->creds.times.renew_till); - o_krb5_cache_clear(); -#endif + printf ("\n"); } diff --git a/misc/openvas-krb5.c b/misc/openvas-krb5.c index d3238ef94..8517f46eb 100644 --- a/misc/openvas-krb5.c +++ b/misc/openvas-krb5.c @@ -1,7 +1,10 @@ #include "openvas-krb5.h" #include +#include +#include #include +#include #include #include #include @@ -68,16 +71,14 @@ o_krb5_find_kdc (const OKrb5Credential *creds, char **kdc) OKrb5ErrorCode result = O_KRB5_REALM_NOT_FOUND; char line[MAX_LINE_LENGTH]; int state = 0; - int last_element; - int i, j; + size_t last_element; + size_t i, j; FILE *file; - int realm_len = strlen (creds->realm); - // we don't know if we should free it or just override it. // aborting instead. GUARD_NULL (*kdc, result); - if ((file = fopen (creds->config_path, "r")) == NULL) + if ((file = fopen ((char *) &creds->config_path.data, "r")) == NULL) { result = O_KRB5_CONF_NOT_FOUND; goto result; @@ -110,17 +111,17 @@ o_krb5_find_kdc (const OKrb5Credential *creds, char **kdc) { for (j = i; j <= last_element; j++) { - if (line[j] != creds->realm[j - i]) + if (line[j] != ((char *) creds->realm.data)[j - i]) { state = 2; break; } - if (j - i >= realm_len) + if (j - i >= creds->realm.len) { break; } } - if (j - i == realm_len) + if (j - i == creds->realm.len) { state = 3; } @@ -175,18 +176,20 @@ o_krb5_add_realm (const OKrb5Credential *creds, const char *kdc) char line[MAX_LINE_LENGTH] = {0}; char tmpfn[MAX_LINE_LENGTH] = {0}; int state, i; - if ((file = fopen (creds->config_path, "r")) == NULL) + char *cp = (char *) creds->config_path.data; + char *realm = (char *) creds->realm.data; + if ((file = fopen (cp, "r")) == NULL) { - if ((file = fopen (creds->config_path, "w")) == NULL) + if ((file = fopen (cp, "w")) == NULL) { result = O_KRB5_CONF_NOT_CREATED; goto result; } - CHECK_FPRINTF (result, file, "[realms]\n%s = {\n kdc = %s\n}\n", - creds->realm, kdc); + CHECK_FPRINTF (result, file, "[realms]\n%s = {\n kdc = %s\n}\n", realm, + kdc); goto result; } - snprintf (tmpfn, MAX_LINE_LENGTH, "%s.tmp", creds->config_path); + snprintf (tmpfn, MAX_LINE_LENGTH, "%s.tmp", cp); if ((tmp = fopen (tmpfn, "w")) == NULL) { result = O_KRB5_TMP_CONF_NOT_CREATED; @@ -201,14 +204,14 @@ o_krb5_add_realm (const OKrb5Credential *creds, const char *kdc) SKIP_WS (line, MAX_LINE_LENGTH, 0, i); if (IS_STR_EQUAL (line, MAX_LINE_LENGTH, i, "[realms]", 8) == 1) { - CHECK_FPRINTF (result, tmp, "%s = {\n kdc = %s\n}\n", - creds->realm, kdc); + CHECK_FPRINTF (result, tmp, "%s = {\n kdc = %s\n}\n", realm, + kdc); state = 1; } } } - if (rename (tmpfn, creds->config_path) != 0) + if (rename (tmpfn, cp) != 0) { result = O_KRB5_TMP_CONF_NOT_MOVED; } @@ -238,16 +241,17 @@ o_krb5_authenticate (const OKrb5Credential credentials, OKrb5Element **element) goto result; } - if ((result = - krb5_build_principal (ctx, &me, strlen (credentials.realm), - credentials.realm, credentials.user, NULL))) + if ((result = krb5_build_principal (ctx, &me, credentials.realm.len, + (char *) credentials.realm.data, + credentials.user, NULL))) { result = result + O_KRB5_ERROR; goto result; }; if ((result = krb5_get_init_creds_password ( - ctx, &creds, me, credentials.password, NULL, NULL, 0, NULL, NULL))) + ctx, &creds, me, (char *) credentials.user.password.data, NULL, NULL, + 0, NULL, NULL))) { result = result + O_KRB5_ERROR; goto result; @@ -345,15 +349,15 @@ o_krb5_cache_credential_id (const OKrb5Credential *cred) unsigned long hash = 2166136261; unsigned int prime = 16777219; - for (const char *str = cred->realm; *str; str++) + for (const char *str = cred->realm.data; *str; str++) { hash = (hash ^ *str) * prime; } - for (const char *str = cred->user; *str; str++) + for (const char *str = cred->user.user.data; *str; str++) { hash = (hash ^ *str) * prime; } - for (const char *str = cred->password; *str; str++) + for (const char *str = cred->user.password.data; *str; str++) { hash = (hash ^ *str) * prime; } @@ -379,7 +383,7 @@ OKrb5ErrorCode o_krb5_cache_clear (void) { OKrb5ErrorCode result = O_KRB5_SUCCESS; -size_t i; + size_t i; if (element_cache == NULL) goto result; for (i = 0; i < element_cache->len; i++) @@ -438,7 +442,7 @@ o_krb5_cache_add_element (const OKrb5Credential credentials, } ALLOCATE_AND_CHECK (*out, OKrb5CacheElement, 1, result); - (*out)->credentials = credentials; + (*out)->credentials = &credentials; (*out)->id = o_krb5_cache_credential_id (&credentials); element_cache->elements[element_cache->len] = *out; @@ -499,21 +503,308 @@ o_krb5_cache_request (const OKrb5Credential credentials, const char *data, { OKrb5ErrorCode result = O_KRB5_SUCCESS; + printf ("hi: %s %d\n", __func__, __LINE__); if (element_cache == NULL) o_krb5_cache_init (); + printf ("hi: %s %d\n", __func__, __LINE__); OKrb5CacheElement *element = NULL; if ((result = o_krb5_cache_authenticate (credentials, &element))) { goto result; } + printf ("hi: %s %d\n", __func__, __LINE__); if ((result = o_krb5_request (element->element, data, data_len, out))) { goto result; } + printf ("hi: %s %d\n", __func__, __LINE__); result: return result; } #endif + +// GSS stuff, remove rest except for REALM handling +#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11 +#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID \ + "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05" +#ifndef gss_mech_spnego +gss_OID_desc spnego_mech_oid_desc = {6, (void *) "\x2b\x06\x01\x05\x05\x02"}; +#define gss_mech_spnego (&spnego_mech_oid_desc) +#endif + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof (a[0])) + +struct OKrb5GSSCredentials +{ + gss_cred_id_t gss_creds; +}; + +struct OKrb5GSSContext +{ + gss_cred_id_t gss_creds; + gss_ctx_id_t gss_ctx; + gss_name_t gss_target; + gss_OID gss_mech; + OM_uint32 gss_want_flags; + OM_uint32 gss_time_req; + gss_channel_bindings_t gss_channel_bindings; + gss_OID gss_actual_mech_type; + OM_uint32 gss_got_flags; + OM_uint32 gss_time_rec; +}; + +static OKrb5ErrorCode +okrb5_gss_authenticate (const OKrb5Credential *creds, + struct OKrb5GSSContext *gss_creds) +{ + char *user_principal; + const struct OKrb5User *user = &creds->user; + + OKrb5ErrorCode result = O_KRB5_SUCCESS; + ALLOCATE_AND_CHECK (user_principal, char, + user->user.len + creds->realm.len + 2, result); + sprintf (user_principal, "%s@%s", (char *) user->user.data, + (char *) creds->realm.data); + + gss_name_t gss_username = GSS_C_NO_NAME; + OM_uint32 maj_stat; + OM_uint32 min_stat; + // OM_uint32 dummy_min_stat; + gss_buffer_desc userbuf = { + .value = user_principal, + .length = strlen (user_principal), + }; + gss_buffer_desc pwbuf = { + .value = user->password.data, + .length = user->password.len, + }; + gss_OID_desc elements[] = { + *gss_mech_krb5, +#ifdef __USE_IAKERB + *gss_mech_iakerb, +#endif /* __USE_IAKERB */ + *gss_mech_spnego, + }; + gss_OID_set_desc creds_mechs = { + .elements = elements, + .count = ARRAY_SIZE (elements), + }; + gss_OID_set_desc spnego_mechs = { + .elements = elements, + .count = ARRAY_SIZE (elements) - 1, /* without gss_mech_spnego */ + }; + gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + + maj_stat = + gss_import_name (&min_stat, &userbuf, GSS_C_NT_USER_NAME, &gss_username); + if (maj_stat != GSS_S_COMPLETE) + { + return O_KRB5_ERROR + maj_stat; + } + + maj_stat = gss_acquire_cred_with_password (&min_stat, gss_username, &pwbuf, 0, + &creds_mechs, GSS_C_INITIATE, + &cred, NULL, NULL); + + //(void) gss_release_name (&dummy_min_stat, &gss_username); + if (maj_stat != GSS_S_COMPLETE) + { + // return NT_STATUS_LOGON_FAILURE; + return O_KRB5_ERROR + maj_stat; + } + + // let spnego only use the desired mechs + maj_stat = gss_set_neg_mechs (&min_stat, cred, &spnego_mechs); + if (maj_stat != GSS_S_COMPLETE) + { + // failed setting neg mechs + return O_KRB5_ERROR + maj_stat; + } + gss_creds->gss_creds = cred; +result: + // TODO: free user_principal on failure? + return result; +} + +struct OKrb5GSSContext * +okrb5_gss_init_context (void) +{ + struct OKrb5GSSContext *context = calloc (1, sizeof (struct OKrb5GSSContext)); + if (context == NULL) + { + return NULL; + } + context->gss_creds = GSS_C_NO_CREDENTIAL; + context->gss_ctx = GSS_C_NO_CONTEXT; + return context; +} + +void +okrb5_gss_free_context (struct OKrb5GSSContext *context) +{ + if (context != NULL) + { + if (context->gss_creds != GSS_C_NO_CREDENTIAL) + { + gss_release_cred (NULL, &context->gss_creds); + } + // TODO: clean rest + free (context); + } +} + +OKrb5ErrorCode +o_krb5_gss_prepare_context (const OKrb5Credential *creds, + struct OKrb5GSSContext *gss_context) +{ + char *target_principal_str = NULL; + OKrb5ErrorCode result = O_KRB5_SUCCESS; + + gss_name_t gss_target = GSS_C_NO_NAME; + OM_uint32 maj_stat; + OM_uint32 min_stat; + gss_buffer_desc targetbuf = GSS_C_EMPTY_BUFFER; + const struct OKrb5Target *target = &creds->target; + + if (gss_context->gss_creds == GSS_C_NO_CREDENTIAL) + { + if ((result = okrb5_gss_authenticate (creds, gss_context))) + { + goto result; + } + } + + if (target->domain.len != 0) + { + ALLOCATE_AND_CHECK (target_principal_str, char, + target->host_name.len + target->domain.len + + target->service.len + creds->realm.len + 4, + result); + sprintf (target_principal_str, "%s/%s/%s@%s", + (char *) target->service.data, (char *) target->host_name.data, + (char *) target->domain.data, (char *) creds->realm.data); + } + else + { + ALLOCATE_AND_CHECK (target_principal_str, char, + target->host_name.len + target->service.len + + creds->realm.len + 3, + result); + sprintf (target_principal_str, "%s/%s@%s", (char *) target->service.data, + (char *) target->host_name.data, (char *) creds->realm.data); + } + + targetbuf = (gss_buffer_desc){ + .value = target_principal_str, + .length = strlen (target_principal_str), + }; + + maj_stat = gss_import_name (&min_stat, &targetbuf, + // might also be GSS_C_NT_HOSTBASED_SERVICE, + // but samba uses GSS_C_NT_USER_NAME + GSS_C_NT_USER_NAME, &gss_target); + if (maj_stat != GSS_S_COMPLETE) + { + result = O_KRB5_ERROR + maj_stat; + goto result; + } + + gss_context->gss_target = gss_target; + // gss_set_neg_mechs() already specified that we want gss_mech_krb5 + // and/or gss_mech_iakerb + // so we use spnego to do the negotiation + gss_context->gss_mech = gss_mech_spnego; + gss_context->gss_want_flags = GSS_C_MUTUAL_FLAG | GSS_C_DELEG_POLICY_FLAG + | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG + | GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG; + gss_context->gss_got_flags = 0; + gss_context->gss_channel_bindings = GSS_C_NO_CHANNEL_BINDINGS; + gss_context->gss_time_req = 0; + gss_context->gss_time_rec = 0; + gss_context->gss_actual_mech_type = NULL; +result: + // TODO: cleanup target_principal_str on failure? + + return result; +} + +// TODO: this signature feels unintuitive based on the mix of in and out and +// changed gss_context as well... +OKrb5ErrorCode +o_krb5_gss_update_context (struct OKrb5GSSContext *gss_context, + const struct OKrb5Slice *in_data, + struct OKrb5Slice **out_data, bool *more) +{ + OM_uint32 maj_stat; + OM_uint32 min_stat; + OKrb5ErrorCode result = O_KRB5_SUCCESS; + // TODO: validate in data + gss_buffer_desc in_buf = { + .length = in_data->len, + .value = in_data->data, + }; + gss_buffer_desc out_buf = GSS_C_EMPTY_BUFFER; + + maj_stat = gss_init_sec_context ( + &min_stat, gss_context->gss_creds, &gss_context->gss_ctx, + gss_context->gss_target, gss_context->gss_mech, gss_context->gss_want_flags, + gss_context->gss_time_req, gss_context->gss_channel_bindings, &in_buf, + &gss_context->gss_actual_mech_type, &out_buf, &gss_context->gss_got_flags, + &gss_context->gss_time_rec); + if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) + { + result = O_KRB5_ERROR + maj_stat; + goto result; + } + *out_data = malloc (sizeof (struct OKrb5Slice)); + (*out_data)->data = calloc (1, out_buf.length); + memcpy ((*out_data)->data, out_buf.value, out_buf.length); + printf ("out_buf.length: %lu\n", out_buf.length); + (*out_data)->len = out_buf.length; + + gss_release_buffer (&min_stat, &out_buf); + *more = maj_stat == GSS_S_CONTINUE_NEEDED; +result: + return result; +} + +OKrb5ErrorCode +o_krb5_gss_session_key_context (struct OKrb5GSSContext *gss_context, + struct OKrb5Slice **out) +{ + OM_uint32 maj_stat; + OM_uint32 min_stat; + OKrb5ErrorCode result = O_KRB5_SUCCESS; + gss_OID_desc gse_sesskey_inq_oid = { + GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH, + (void *) GSS_KRB5_INQ_SSPI_SESSION_KEY_OID, + }; + gss_buffer_set_t set = GSS_C_NO_BUFFER_SET; + + maj_stat = gss_inquire_sec_context_by_oid (&min_stat, gss_context->gss_ctx, + &gse_sesskey_inq_oid, &set); + if (maj_stat != GSS_S_COMPLETE) + { + result = O_KRB5_ERROR + maj_stat; + goto result; + } + + if ((set == GSS_C_NO_BUFFER_SET) || (set->count == 0) + || (set->elements[0].length == 0)) + { + result = O_KRB5_ERROR + GSS_S_BAD_SIG; + goto result; + } + + // TODO: verify out + *out = calloc (1, sizeof (struct OKrb5Slice)); + (*out)->data = malloc (set->elements[0].length); + memcpy ((*out)->data, set->elements[0].value, set->elements[0].length); + (*out)->len = set->elements[0].length; + gss_release_buffer_set (&min_stat, &set); +result: + return result; +} diff --git a/misc/openvas-krb5.h b/misc/openvas-krb5.h index a7f82e370..cda1596fa 100644 --- a/misc/openvas-krb5.h +++ b/misc/openvas-krb5.h @@ -1,4 +1,5 @@ #include +#include #ifndef OPENVAS_KRB5 #define OPENVAS_KRB5 1 #include @@ -38,14 +39,40 @@ typedef struct krb5_creds creds; } OKrb5Element; +struct OKrb5Slice +{ + void *data; + size_t len; +}; + +struct OKrb5User +{ + struct OKrb5Slice user; + struct OKrb5Slice password; +}; + +struct OKrb5Target +{ + struct OKrb5Slice host_name; + struct OKrb5Slice service; + struct OKrb5Slice domain; +}; + typedef struct { - const char *config_path; - const char *realm; - const char *user; - const char *password; + struct OKrb5Slice config_path; + struct OKrb5Slice realm; + // required for the case that the realm is not configured in the krb5.conf + // will be ignored otherwise. + struct OKrb5Slice kdc; + struct OKrb5User user; + struct OKrb5Target target; } OKrb5Credential; + + +// TODO: initializer with default values and NULL + typedef struct { krb5_data data; @@ -85,7 +112,7 @@ o_krb5_free_element (OKrb5Element *element); typedef struct { - OKrb5Credential credentials; + const OKrb5Credential *credentials; OKrb5Element *element; OKrb5ErrorCode last_error_code; unsigned long id; @@ -114,4 +141,39 @@ o_krb5_cache_request (const OKrb5Credential credentials, const char *data, const size_t data_len, OKrb5Data **out); #endif +#define okrb5_slice_from_str(str) \ + (struct OKrb5Slice) \ + { \ + .data = (void *) str, .len = str == NULL ? 0 : strlen (str) \ + } + +#define okrb5_set_slice_from_str(slice, str) \ + do \ + { \ + slice.data = (void *) str; \ + slice.len = str == NULL ? 0 : strlen (str); \ + } \ + while (0) + + +typedef struct OKrb5GSSContext OKrb5GSSContext; +// Unsure about bool type + +OKrb5ErrorCode +o_krb5_gss_session_key_context (struct OKrb5GSSContext *gss_context, + struct OKrb5Slice **out); + +struct OKrb5GSSContext *okrb5_gss_init_context (void); +void okrb5_gss_free_context (struct OKrb5GSSContext *context); + +OKrb5ErrorCode +o_krb5_gss_prepare_context (const OKrb5Credential *creds, + struct OKrb5GSSContext *gss_context); + +OKrb5ErrorCode +o_krb5_gss_update_context (struct OKrb5GSSContext *gss_context, + const struct OKrb5Slice *in_data, + struct OKrb5Slice **out_data, bool *more); + + #endif diff --git a/nasl/nasl_krb5.c b/nasl/nasl_krb5.c index 7b4282598..585a0e396 100644 --- a/nasl/nasl_krb5.c +++ b/nasl/nasl_krb5.c @@ -14,29 +14,35 @@ credential.user, result); OKrb5ErrorCode last_okrb5_result; + +#define set_slice_from_lex_or_env(lexic, slice, name, env_name) \ + do \ + { \ + okrb5_set_slice_from_str (slice, get_str_var_by_name (lexic, name)); \ + if (slice.len == 0) \ + { \ + okrb5_set_slice_from_str (slice, getenv (env_name)); \ + } \ + } \ + while (0) + static OKrb5Credential build_krb5_credential (lex_ctxt *lexic) { OKrb5Credential credential; - credential.user = NULL; - credential.password = NULL; - // neither values from get_str_var_by_name nor getenv must be freed - if ((credential.config_path = get_str_var_by_name (lexic, "config_path")) - == NULL) + memset (&credential, 0, sizeof (OKrb5Credential)); + + set_slice_from_lex_or_env (lexic, credential.config_path, "config_path", + "KRB5_CONFIG"); + if (credential.config_path.len == 0) { - credential.config_path = getenv ("KRB5_CONFIG"); - if (credential.config_path == NULL) - { - credential.config_path = "/etc/krb5.conf"; - } + okrb5_set_slice_from_str (credential.config_path, "/etc/krb5.conf"); } - if ((credential.realm = get_str_var_by_name (lexic, "realm")) == NULL) + // TODO: enhance with redis check? maybe. + set_slice_from_lex_or_env (lexic, credential.realm, "realm", "KRB5_REALM"); + if (credential.realm.len == 0) { - credential.realm = getenv ("KRB5_REALM"); - if (credential.realm == NULL) - { - nasl_print_krb_error (lexic, credential, O_KRB5_REALM_NOT_FOUND); - } + nasl_print_krb_error (lexic, credential, O_KRB5_REALM_NOT_FOUND); } return credential; @@ -114,7 +120,8 @@ nasl_okrb5_add_realm (lex_ctxt *lexic) } tree_cell * -nasl_okrb5_result (lex_ctxt *lexic) { +nasl_okrb5_result (lex_ctxt *lexic) +{ (void) lexic; // TODO: implement function to return string representation of result return NULL; @@ -124,16 +131,19 @@ nasl_okrb5_result (lex_ctxt *lexic) { * @brief Returns 1 if the krb5 function was successful 0 otherwise * * The nasl function has one optional parameter: - * - retval: the return value of the krb5 function. If the value is not defined, the return value of the last krb5 function is used. + * - retval: the return value of the krb5 function. If the value is not defined, + * the return value of the last krb5 function is used. * * - * @param[in] lexic NASL lexer. + * @param[in] lexic NASL lexer. * * @return lex cell containing a number indicating success. */ tree_cell * -nasl_okrb5_is_success (lex_ctxt *lexic) { - OKrb5ErrorCode result = get_int_var_by_name (lexic, "retval", last_okrb5_result); +nasl_okrb5_is_success (lex_ctxt *lexic) +{ + OKrb5ErrorCode result = + get_int_var_by_name (lexic, "retval", last_okrb5_result); tree_cell *retc = alloc_typed_cell (CONST_INT); retc->x.i_val = result == O_KRB5_SUCCESS; return retc; @@ -143,18 +153,20 @@ nasl_okrb5_is_success (lex_ctxt *lexic) { * @brief Returns 0 if the krb5 function was successful and 1 if it failed * * The nasl function has one optional parameter: - * - retval: the return value of the krb5 function. If the value is not defined, the return value of the last krb5 function is used. + * - retval: the return value of the krb5 function. If the value is not defined, + * the return value of the last krb5 function is used. * * - * @param[in] lexic NASL lexer. + * @param[in] lexic NASL lexer. * * @return lex cell containing a number indicating success. */ tree_cell * -nasl_okrb5_is_failure (lex_ctxt *lexic) { - OKrb5ErrorCode result = get_int_var_by_name (lexic, "retval", last_okrb5_result); +nasl_okrb5_is_failure (lex_ctxt *lexic) +{ + OKrb5ErrorCode result = + get_int_var_by_name (lexic, "retval", last_okrb5_result); tree_cell *retc = alloc_typed_cell (CONST_INT); retc->x.i_val = result != O_KRB5_SUCCESS; return retc; } -