diff --git a/kerberos/authenticate_test.c b/kerberos/authenticate_test.c index 30ed91240..e35c008ad 100644 --- a/kerberos/authenticate_test.c +++ b/kerberos/authenticate_test.c @@ -4,25 +4,27 @@ #include #include -#define GUARD_ENV_SET(var, env) \ - do \ - { \ - var = okrb5_slice_from_str (getenv (env)); \ - if (var.len == 0) \ - { \ - fprintf (stderr, env " is not set\n"); \ - return 1; \ - } \ - } \ +#define GUARD_ENV_SET(var, env) \ + do \ + { \ + okrb5_set_slice_from_str (var, getenv (env)); \ + if (var.len == 0) \ + { \ + fprintf (stderr, env " is not set\n"); \ + return 1; \ + } \ + } \ while (0) +struct OKrb5GSSContext *cached_gss_context = NULL; int main () { char *kdc = NULL; OKrb5ErrorCode result = O_KRB5_SUCCESS; OKrb5Credential credentials; - OKrb5GSSContext *context = NULL; + + memset (&credentials, 0, sizeof (OKrb5Credential)); struct OKrb5Slice from_application = {.data = NULL, .len = 0}; struct OKrb5Slice *to_application = NULL; bool more = false; @@ -50,17 +52,17 @@ main () // printf ("Using kdc: %s\n", kdc); // free (kdc); // } - context = okrb5_gss_init_context (); + cached_gss_context = okrb5_gss_init_context (); printf ("Using realm: %s\n", (char *) credentials.realm.data); - if ((result = o_krb5_gss_prepare_context (&credentials, context))) + if ((result = o_krb5_gss_prepare_context (&credentials, cached_gss_context))) { fprintf (stderr, "Unable to prepare context: %d\n", result); return 1; } 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))) + if ((result = o_krb5_gss_update_context ( + cached_gss_context, &from_application, &to_application, &more))) { fprintf (stderr, "Unable to update context: %d\n", result); return 1; diff --git a/misc/openvas-krb5.c b/misc/openvas-krb5.c index 8517f46eb..e747d2dde 100644 --- a/misc/openvas-krb5.c +++ b/misc/openvas-krb5.c @@ -669,6 +669,7 @@ o_krb5_gss_prepare_context (const OKrb5Credential *creds, 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))) diff --git a/misc/openvas-krb5.h b/misc/openvas-krb5.h index cda1596fa..a61952343 100644 --- a/misc/openvas-krb5.h +++ b/misc/openvas-krb5.h @@ -164,6 +164,7 @@ 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 diff --git a/nasl/nasl_init.c b/nasl/nasl_init.c index db4bdfd48..c09375510 100644 --- a/nasl/nasl_init.c +++ b/nasl/nasl_init.c @@ -23,12 +23,11 @@ #include "nasl_http.h" #include "nasl_http2.h" #include "nasl_isotime.h" +#include "nasl_krb5.h" #include "nasl_lex_ctxt.h" #include "nasl_misc_funcs.h" #include "nasl_packet_forgery.h" #include "nasl_packet_forgery_v6.h" -#include "nasl_krb5.h" - #include /* for getenv. */ #include /* for memset */ @@ -91,7 +90,7 @@ static init_func libfuncs[] = { {"get_host_kb_index", get_host_kb_index}, {"security_message", security_message}, {"log_message", log_message}, - {"error_message", error_message}, + {"error_message", error_message2}, {"open_sock_tcp", nasl_open_sock_tcp}, {"open_sock_udp", nasl_open_sock_udp}, {"open_priv_sock_tcp", nasl_open_priv_sock_tcp}, @@ -417,7 +416,14 @@ static init_func libfuncs[] = { {"isotime_print", nasl_isotime_print}, {"isotime_add", nasl_isotime_add}, // krb5 - {"krb5_find_kdc", nasl_okrb5_find_kdc }, + {"krb5_find_kdc", nasl_okrb5_find_kdc}, + {"krb5_is_success", nasl_okrb5_is_success}, + {"krb5_is_failure", nasl_okrb5_is_failure}, + {"krb5_gss_init", nasl_okrb5_gss_init}, + {"krb5_gss_prepare_context", nasl_okrb5_gss_prepare_context}, + {"krb5_gss_update_context", nasl_okrb5_gss_update_context}, + {"krb5_gss_update_context_needs_more", nasl_okrb5_gss_update_context_needs_more}, + {"krb5_gss_update_context_out", nasl_okrb5_gss_update_context_out}, {NULL, NULL}}; /* String variables */ diff --git a/nasl/nasl_krb5.c b/nasl/nasl_krb5.c index 585a0e396..e8b8e2af7 100644 --- a/nasl/nasl_krb5.c +++ b/nasl/nasl_krb5.c @@ -7,11 +7,13 @@ #include "nasl_lex_ctxt.h" #include "nasl_tree.h" #include "nasl_var.h" + +#include // TODO: add string function for result -#define nasl_print_krb_error(lexic, credential, result) \ - nasl_perror (lexic, "%s[config_path: %s realm: %s user: %s] => %d", \ - __func__, credential.config_path, credential.realm, \ - credential.user, result); +#define nasl_print_krb_error(lexic, credential, result) \ + nasl_perror (lexic, "%s[config_path: '%s' realm: '%s' user: '%s'] => %d", \ + __func__, credential.config_path.data, credential.realm.data, \ + credential.user.user.data, result); OKrb5ErrorCode last_okrb5_result; @@ -26,6 +28,18 @@ OKrb5ErrorCode last_okrb5_result; } \ while (0) +#define perror_set_slice_from_lex_or_env(lexic, slice, name, env_name) \ + do \ + { \ + set_slice_from_lex_or_env (lexic, slice, name, env_name); \ + if (slice.len == 0) \ + { \ + nasl_perror (lexic, "Expected %s or env variable %s", name, \ + env_name); \ + } \ + } \ + while (0) + static OKrb5Credential build_krb5_credential (lex_ctxt *lexic) { @@ -39,11 +53,24 @@ build_krb5_credential (lex_ctxt *lexic) okrb5_set_slice_from_str (credential.config_path, "/etc/krb5.conf"); } // TODO: enhance with redis check? maybe. - set_slice_from_lex_or_env (lexic, credential.realm, "realm", "KRB5_REALM"); - if (credential.realm.len == 0) + + perror_set_slice_from_lex_or_env (lexic, credential.realm, "realm", + "KRB5_REALM"); + perror_set_slice_from_lex_or_env (lexic, credential.user.user, "user", + "KRB5_USER"); + perror_set_slice_from_lex_or_env (lexic, credential.user.password, "password", + "KRB5_PASSWORD"); + perror_set_slice_from_lex_or_env (lexic, credential.target.host_name, "host", + "KRB5_TARGET_HOST"); + // set_slice_from_lex_or_env (lexic, credential.target.service, "service", + // "KRB5_TARGET_SERVICE"); + if (credential.target.service.len == 0) { - nasl_print_krb_error (lexic, credential, O_KRB5_REALM_NOT_FOUND); + okrb5_set_slice_from_str (credential.target.service, "cifs"); } + set_slice_from_lex_or_env (lexic, credential.kdc, "kdc", "KRB5_KDC"); + + memset (&credential.target.domain, 0, sizeof (struct OKrb5Slice)); return credential; } @@ -79,7 +106,7 @@ nasl_okrb5_find_kdc (lex_ctxt *lexic) if ((last_okrb5_result = o_krb5_find_kdc (&credential, &kdc))) { nasl_print_krb_error (lexic, credential, last_okrb5_result); - return NULL; + return FAKE_CELL; } retc = alloc_typed_cell (CONST_DATA); @@ -142,8 +169,7 @@ nasl_okrb5_result (lex_ctxt *lexic) tree_cell * nasl_okrb5_is_success (lex_ctxt *lexic) { - OKrb5ErrorCode result = - get_int_var_by_name (lexic, "retval", last_okrb5_result); + OKrb5ErrorCode result = get_int_var_by_num (lexic, 0, last_okrb5_result); tree_cell *retc = alloc_typed_cell (CONST_INT); retc->x.i_val = result == O_KRB5_SUCCESS; return retc; @@ -164,9 +190,153 @@ nasl_okrb5_is_success (lex_ctxt *lexic) tree_cell * nasl_okrb5_is_failure (lex_ctxt *lexic) { - OKrb5ErrorCode result = - get_int_var_by_name (lexic, "retval", last_okrb5_result); + OKrb5ErrorCode result = get_int_var_by_num (lexic, 0, last_okrb5_result); tree_cell *retc = alloc_typed_cell (CONST_INT); retc->x.i_val = result != O_KRB5_SUCCESS; return retc; } + +// TODO: may need a cacing mechanism for different configurations +// for now we just use one +struct OKrb5GSSContext *cached_gss_context = NULL; + +tree_cell * +nasl_okrb5_gss_init (lex_ctxt *lexic) +{ + (void) lexic; + if (cached_gss_context != NULL) + { + okrb5_gss_free_context (cached_gss_context); + } + cached_gss_context = okrb5_gss_init_context (); + if (cached_gss_context == NULL) + { + last_okrb5_result = O_KRB5_EXPECTED_NOT_NULL; + } + else + { + last_okrb5_result = O_KRB5_SUCCESS; + }; + tree_cell *retc = alloc_typed_cell (CONST_INT); + retc->x.i_val = last_okrb5_result; + return retc; +} +tree_cell * +nasl_okrb5_gss_prepare_context (lex_ctxt *lexic) +{ + (void) lexic; + + OKrb5Credential credential; + credential = build_krb5_credential (lexic); + OKrb5ErrorCode result = O_KRB5_SUCCESS; + if (cached_gss_context == NULL) + { + cached_gss_context = okrb5_gss_init_context (); + } + result = o_krb5_gss_prepare_context (&credential, cached_gss_context); + tree_cell *retc = alloc_typed_cell (CONST_INT); + retc->x.i_val = result; + last_okrb5_result = result; + return retc; +} + +struct OKrb5Slice *to_application = NULL; +bool gss_update_context_more = false; + +tree_cell * +nasl_okrb5_gss_update_context (lex_ctxt *lexic) +{ + (void) lexic; + OKrb5ErrorCode result = O_KRB5_SUCCESS; + tree_cell *retc; + struct OKrb5Slice from_application; + + if (to_application != NULL) + { + free (to_application->data); + free (to_application); + to_application = NULL; + } + + okrb5_set_slice_from_str (from_application, get_str_var_by_num (lexic, 0)); + + if (cached_gss_context == NULL) + { + last_okrb5_result = O_KRB5_EXPECTED_NOT_NULL; + goto result; + } + result = + o_krb5_gss_update_context (cached_gss_context, &from_application, + &to_application, &gss_update_context_more); +result: + retc = alloc_typed_cell (CONST_INT); + retc->x.i_val = result; + last_okrb5_result = result; + return retc; +} + +tree_cell * +nasl_okrb5_gss_update_context_needs_more (lex_ctxt *lexic) +{ + (void) lexic; + tree_cell *retc = alloc_typed_cell (CONST_INT); + retc->x.i_val = gss_update_context_more; + return retc; +} + +tree_cell * +nasl_okrb5_gss_update_context_out (lex_ctxt *lexic) +{ + (void) lexic; + if (to_application == NULL) + { + return FAKE_CELL; + } + tree_cell *retc = alloc_typed_cell (CONST_DATA); + retc->x.str_val = to_application->data; + retc->size = to_application->len; + return retc; +} + +/* + context = okrb5_gss_init_context (); + printf ("Using realm: %s\n", (char *) credentials.realm.data); + if ((result = o_krb5_gss_prepare_context (&credentials, context))) + { + return 1; + } + 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))) + { + return 1; + } + printf ("success: %d: outdata_len: %zu\n", result, to_application->len); + + for (size_t i = 0; i < to_application->len; i++) + { + printf ("%02x", ((char *) to_application->data)[i]); + } + printf ("\n"); + +*/ + +/* +*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); +*/ diff --git a/nasl/nasl_krb5.h b/nasl/nasl_krb5.h index 5095b2794..6464ef9be 100644 --- a/nasl/nasl_krb5.h +++ b/nasl/nasl_krb5.h @@ -81,3 +81,20 @@ nasl_okrb5_is_success (lex_ctxt *lexic); tree_cell * nasl_okrb5_is_failure (lex_ctxt *lexic); +tree_cell * +nasl_okrb5_gss_init (lex_ctxt *lexic); + + +tree_cell * +nasl_okrb5_gss_prepare_context (lex_ctxt *lexic); + + +tree_cell * +nasl_okrb5_gss_update_context (lex_ctxt *lexic); + + +tree_cell * +nasl_okrb5_gss_update_context_needs_more(lex_ctxt *lexic); + +tree_cell * +nasl_okrb5_gss_update_context_out (lex_ctxt *lexic); diff --git a/nasl/nasl_scanner_glue.c b/nasl/nasl_scanner_glue.c index 0338c7420..34abfe2a2 100644 --- a/nasl/nasl_scanner_glue.c +++ b/nasl/nasl_scanner_glue.c @@ -1024,8 +1024,9 @@ log_message (lex_ctxt *lexic) return security_something (lexic, proto_post_log, post_log_with_uri); } +// FIXME: the name of the function is too broad, krb5 people also hate prefixes tree_cell * -error_message (lex_ctxt *lexic) +error_message2 (lex_ctxt *lexic) { return security_something (lexic, proto_post_error, post_error); } diff --git a/nasl/nasl_scanner_glue.h b/nasl/nasl_scanner_glue.h index 5ea732f19..113efb9f9 100644 --- a/nasl/nasl_scanner_glue.h +++ b/nasl/nasl_scanner_glue.h @@ -101,7 +101,7 @@ tree_cell * log_message (lex_ctxt *); tree_cell * -error_message (lex_ctxt *); +error_message2 (lex_ctxt *); tree_cell * nasl_scanner_get_port (lex_ctxt *); diff --git a/rust/examples/.gitignore b/rust/examples/.gitignore new file mode 100644 index 000000000..73d41de61 --- /dev/null +++ b/rust/examples/.gitignore @@ -0,0 +1 @@ +test.sh diff --git a/rust/examples/gss.nasl b/rust/examples/gss.nasl new file mode 100644 index 000000000..301f5e27d --- /dev/null +++ b/rust/examples/gss.nasl @@ -0,0 +1,31 @@ +display('do more hate-driven development'); +result = krb5_gss_init(); +if (krb5_is_failure(result)) { + display('oh nooo, unable to init gss context'); + exit(42); +} +display("Got context, the easiest part is done."); +display("Keep in mind that gss_init does override previous context."); +#result = krb5_gss_prepare_context(realm: 'KBKERB.LOCAL', host: 'WIN-MPDRO9RF6Q8.gbkerb.local', service: 'cifs', user: 'gbadmin', password: '*********'); +result = krb5_gss_prepare_context(); +if (krb5_is_failure()) { + display('oh nooo, unable to authenticate, did you check vpn? Yes, oh.'); + exit(42); +} +display("We got authenticated.... keep in mint that the first update context must be without data ..."); +result = krb5_gss_update_context(); +if (krb5_is_failure()) { + display('oh nooo, unable to initially update context, did you check vpn? Yes, oh.'); + exit(42); +} +if (krb5_gss_update_context_needs_more()) { + display('continue to send data to update_context...'); +} + +out = krb5_gss_update_context_out(); +if (out) { + display(hexstr(out)); +} else { + display('no data?!'); +} +