OpenVAS Scanner 23.43.1
nasl_krb5.c
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025 Greenbone AG
2//
3// SPDX-License-Identifier: GPL-2.0-or-later WITH x11vnc-openssl-exception
4
5#include "nasl_krb5.h"
6
8#include "nasl_debug.h"
9#include "nasl_func.h"
10#include "nasl_global_ctxt.h"
11#include "nasl_lex_ctxt.h"
12#include "nasl_tree.h"
13#include "nasl_var.h"
14
15#include <gvm/base/networking.h>
16#include <netinet/in.h>
17#include <stdio.h>
18#include <string.h>
19#include <unistd.h>
20
21#define NASL_PRINT_KRB_ERROR(lexic, credential, result) \
22 do \
23 { \
24 char *error_str = okrb5_error_code_to_string (result); \
25 nasl_perror ( \
26 lexic, "%s[config_path: '%s' realm: '%s' user: '%s'] => %s (%d)", \
27 __func__, credential.config_path.data, credential.realm.data, \
28 credential.user.user.data, error_str, result); \
29 free (error_str); \
30 } \
31 while (0)
32
33// Is used for krb5_is_success, krb5_is_failure which allows the script author
34// to verify if the last called krb5 function failed or not. This is strictly
35// speaking a safety net for incorrect usage as most krb5 functions return
36// the error code.
38
39// cached_gss_context is used on cases that require an already existing session.
40// NASL does currently not have the concept of a pointer nor struct so we need
41// to store it as a global variable.
42//
43// We use one context per run, this means that per run (target + oid) there is
44// only on credential allowed making it safe to be cached in that fashion.
45static struct OKrb5GSSContext *cached_gss_context = NULL;
46
47// Is used for `krb5_gss_update_context_out` and is essential a
48// cache for the data from `krb5_gss_update_context`.
49static struct OKrb5Slice *to_application = NULL;
50
51// Is used for `krb5_gss_update_context_needs_more` which indicates to the
52// script author that `krb5_gss_update_context` is not satisfied yet.
53static bool gss_update_context_more = false;
54
55// Stores the path to the generated krb5 config file for cleanup.
56static char *generated_config_path = NULL;
57
58#define SET_SLICE_FROM_LEX_OR_ENV(lexic, slice, name, env_name) \
59 do \
60 { \
61 okrb5_set_slice_from_str (slice, get_str_var_by_name (lexic, name)); \
62 if (slice.len == 0) \
63 { \
64 okrb5_set_slice_from_str (slice, getenv (env_name)); \
65 } \
66 else \
67 { \
68 setenv (env_name, get_str_var_by_name (lexic, name), 1); \
69 } \
70 } \
71 while (0)
72
73#define PERROR_SET_SLICE_FROM_LEX_OR_ENV(lexic, slice, name, env_name) \
74 do \
75 { \
76 SET_SLICE_FROM_LEX_OR_ENV (lexic, slice, name, env_name); \
77 if (slice.len == 0) \
78 { \
79 nasl_perror (lexic, "Expected %s or env variable %s", name, \
80 env_name); \
81 } \
82 } \
83 while (0)
84
85static OKrb5Credential
87{
88 OKrb5Credential credential = {0};
90
91 char *kdc = NULL;
92
93 SET_SLICE_FROM_LEX_OR_ENV (lexic, credential.config_path, "config_path",
94 "KRB5_CONFIG");
95 if (credential.config_path.len == 0)
96 {
97 char *ip_str = addr6_as_str (lexic->script_infos->ip);
98 for (int i = 0; ip_str[i] != '\0'; i++)
99 {
100 if (ip_str[i] == '.' || ip_str[i] == ':')
101 {
102 ip_str[i] = '_';
103 }
104 }
105 char default_config_path[256];
106 snprintf (default_config_path, sizeof (default_config_path),
107 "/tmp/krb5_%s.conf", ip_str);
108 setenv ("KRB5_CONFIG", default_config_path, 1);
109 okrb5_set_slice_from_str (credential.config_path, default_config_path);
110 }
111
112 // Store path for cleanup
113 if (generated_config_path != NULL)
116 strndup (credential.config_path.data, credential.config_path.len);
117
118 PERROR_SET_SLICE_FROM_LEX_OR_ENV (lexic, credential.realm, "realm",
119 "KRB5_REALM");
120 PERROR_SET_SLICE_FROM_LEX_OR_ENV (lexic, credential.kdc, "kdc", "KRB5_KDC");
121 PERROR_SET_SLICE_FROM_LEX_OR_ENV (lexic, credential.user.user, "user",
122 "KRB5_USER");
123 PERROR_SET_SLICE_FROM_LEX_OR_ENV (lexic, credential.user.password, "password",
124 "KRB5_PASSWORD");
125 PERROR_SET_SLICE_FROM_LEX_OR_ENV (lexic, credential.target.host_name, "host",
126 "KRB5_TARGET_HOST");
127 // SET_SLICE_FROM_LEX_OR_ENV (lexic, credential.target.service, "service",
128 // "KRB5_TARGET_SERVICE");
129
130 if ((code = o_krb5_find_kdc (&credential, &kdc)))
131 {
133 {
134 NASL_PRINT_KRB_ERROR (lexic, credential, code);
135 }
136 else
137 {
138 if ((code = o_krb5_add_realm (&credential, credential.kdc.data)))
139 {
140 NASL_PRINT_KRB_ERROR (lexic, credential, code);
141 }
142 }
143 }
144 else
145 {
146 free (kdc);
147 }
148 if (credential.target.service.len == 0)
149 {
150 okrb5_set_slice_from_str (credential.target.service, "cifs");
151 }
152 SET_SLICE_FROM_LEX_OR_ENV (lexic, credential.kdc, "kdc", "KRB5_KDC");
153
154 memset (&credential.target.domain, 0, sizeof (struct OKrb5Slice));
155
156 return credential;
157}
158
178tree_cell *
180{
181 tree_cell *retc;
182 char *kdc = NULL;
183 OKrb5Credential credential;
184
185 credential = build_krb5_credential (lexic);
186
187 if ((last_okrb5_result = o_krb5_find_kdc (&credential, &kdc)))
188 {
189 NASL_PRINT_KRB_ERROR (lexic, credential, last_okrb5_result);
190 return FAKE_CELL;
191 }
192
194 retc->x.str_val = kdc;
195 retc->size = strlen (kdc);
196 return retc;
197}
198
199tree_cell *
201{
202 tree_cell *retc;
203 OKrb5Credential credential;
204 char *kdc = get_str_var_by_name (lexic, "kdc");
205 if (kdc == NULL)
206 {
207 kdc = getenv ("KRB5_KDC");
208 if (kdc == NULL)
209 {
211 NASL_PRINT_KRB_ERROR (lexic, credential, last_okrb5_result);
212 goto exit;
213 }
214 }
215
216 credential = build_krb5_credential (lexic);
217
218 if ((last_okrb5_result = o_krb5_add_realm (&credential, kdc)))
219 {
220 NASL_PRINT_KRB_ERROR (lexic, credential, last_okrb5_result);
221 }
222
223exit:
225 retc->x.i_val = last_okrb5_result;
226 return retc;
227}
228
241tree_cell *
243{
246 retc->x.i_val = result == O_KRB5_SUCCESS;
247 return retc;
248}
249
262tree_cell *
264{
267 retc->x.i_val = result != O_KRB5_SUCCESS;
268 return retc;
269}
270
271tree_cell *
273{
274 (void) lexic;
276 if (cached_gss_context == NULL)
277 {
279 }
280 else
281 {
283 };
285 retc->x.i_val = last_okrb5_result;
286 return retc;
287}
288tree_cell *
290{
291 (void) lexic;
292
293 OKrb5Credential credential;
294 credential = build_krb5_credential (lexic);
296 if (cached_gss_context == NULL)
297 {
299 }
300 result = o_krb5_gss_prepare_context (&credential, cached_gss_context);
302 retc->x.i_val = result;
303 last_okrb5_result = result;
304 return retc;
305}
306
307tree_cell *
309{
311 tree_cell *retc;
312 struct OKrb5Slice from_application;
313
314 if (to_application != NULL)
315 {
316 free (to_application->data);
318 to_application = NULL;
319 }
320
321 from_application.data = (void *) get_str_var_by_num (lexic, 0);
322 from_application.len = get_var_size_by_num (lexic, 0);
323
324 if (cached_gss_context == NULL)
325 {
327 goto result;
328 }
329 result =
332result:
334 retc->x.i_val = result;
335 last_okrb5_result = result;
336 return retc;
337}
338
339void
341{
342 if (to_application != NULL)
343 {
344 free (to_application->data);
346 to_application = NULL;
347 }
348 if (cached_gss_context != NULL)
349 {
351 cached_gss_context = NULL;
352 }
353 if (generated_config_path != NULL)
354 {
355 unlink (generated_config_path);
358 }
359}
360
361tree_cell *
363{
364 (void) lexic;
367 return retc;
368}
369
370static inline tree_cell *
372{
374 retc->x.str_val = slice->data;
375 retc->size = slice->len;
376 return retc;
377}
378
379tree_cell *
381{
382 (void) lexic;
383 if (to_application == NULL)
384 {
385 return FAKE_CELL;
386 }
388 // we need to prevent accidental free it as it is freed when the tree_cell is
389 // cleaned up
390 to_application = NULL;
391 return out;
392}
393
394tree_cell *
396{
397 (void) lexic;
398 struct OKrb5Slice *session_key = NULL;
399 if (cached_gss_context == NULL)
400 {
402 return FAKE_CELL;
403 }
404 if ((last_okrb5_result =
407 {
408 return FAKE_CELL;
409 }
410 return okrb5_slice_to_tree_cell (session_key);
411}
412
413tree_cell *
415{
416 (void) lexic;
419 retc->size = strlen (retc->x.str_val);
420 return retc;
421}
void free(void *)
tree_cell * nasl_okrb5_is_failure(lex_ctxt *lexic)
Returns 0 if the krb5 function was successful and 1 if it failed.
Definition nasl_krb5.c:263
static char * generated_config_path
Definition nasl_krb5.c:56
static struct OKrb5Slice * to_application
Definition nasl_krb5.c:49
tree_cell * nasl_okrb5_find_kdc(lex_ctxt *lexic)
Returns the defined KDC of a given Realm.
Definition nasl_krb5.c:179
tree_cell * nasl_okrb5_gss_session_key_context(lex_ctxt *lexic)
Definition nasl_krb5.c:395
tree_cell * nasl_okrb5_add_realm(lex_ctxt *lexic)
Adds the given KDC to the given Realm.
Definition nasl_krb5.c:200
tree_cell * nasl_okrb5_gss_update_context_out(lex_ctxt *lexic)
Definition nasl_krb5.c:380
tree_cell * nasl_okrb5_gss_update_context_needs_more(lex_ctxt *lexic)
Definition nasl_krb5.c:362
#define PERROR_SET_SLICE_FROM_LEX_OR_ENV(lexic, slice, name, env_name)
Definition nasl_krb5.c:73
static struct OKrb5GSSContext * cached_gss_context
Definition nasl_krb5.c:45
tree_cell * nasl_okrb5_gss_update_context(lex_ctxt *lexic)
Definition nasl_krb5.c:308
tree_cell * nasl_okrb5_gss_prepare_context(lex_ctxt *lexic)
Definition nasl_krb5.c:289
tree_cell * nasl_okrb5_error_code_to_string(lex_ctxt *lexic)
Definition nasl_krb5.c:414
#define SET_SLICE_FROM_LEX_OR_ENV(lexic, slice, name, env_name)
Definition nasl_krb5.c:58
tree_cell * nasl_okrb5_gss_init(lex_ctxt *lexic)
Definition nasl_krb5.c:272
static OKrb5ErrorCode last_okrb5_result
Definition nasl_krb5.c:37
tree_cell * nasl_okrb5_is_success(lex_ctxt *lexic)
Returns 1 if the krb5 function was successful 0 otherwise.
Definition nasl_krb5.c:242
void nasl_okrb5_clean(void)
Definition nasl_krb5.c:340
#define NASL_PRINT_KRB_ERROR(lexic, credential, result)
Definition nasl_krb5.c:21
static OKrb5Credential build_krb5_credential(lex_ctxt *lexic)
Definition nasl_krb5.c:86
static bool gss_update_context_more
Definition nasl_krb5.c:53
static tree_cell * okrb5_slice_to_tree_cell(struct OKrb5Slice *slice)
Definition nasl_krb5.c:371
long int get_var_size_by_num(lex_ctxt *, int)
Definition nasl_var.c:1145
struct struct_lex_ctxt lex_ctxt
char * get_str_var_by_name(lex_ctxt *, const char *)
Definition nasl_var.c:1118
char * get_str_var_by_num(lex_ctxt *, int)
Definition nasl_var.c:1108
long int get_int_var_by_num(lex_ctxt *, int, int)
Definition nasl_var.c:1094
#define code
tree_cell * alloc_typed_cell(int typ)
Definition nasl_tree.c:25
@ CONST_DATA
Definition nasl_tree.h:82
@ CONST_STR
Definition nasl_tree.h:80
@ CONST_INT
Definition nasl_tree.h:79
struct TC tree_cell
#define FAKE_CELL
Definition nasl_tree.h:110
char * okrb5_error_code_to_string(const OKrb5ErrorCode code)
void okrb5_gss_free_context(struct OKrb5GSSContext *context)
OKrb5ErrorCode o_krb5_add_realm(const OKrb5Credential *creds, const char *kdc)
OKrb5ErrorCode o_krb5_find_kdc(const OKrb5Credential *creds, char **kdc)
OKrb5ErrorCode o_krb5_gss_prepare_context(const OKrb5Credential *creds, struct OKrb5GSSContext *gss_context)
OKrb5ErrorCode o_krb5_gss_session_key_context(struct OKrb5GSSContext *gss_context, struct OKrb5Slice **out)
struct OKrb5GSSContext * okrb5_gss_init_context(void)
OKrb5ErrorCode o_krb5_gss_update_context(struct OKrb5GSSContext *gss_context, const struct OKrb5Slice *in_data, struct OKrb5Slice **out_data, bool *more)
OKrb5ErrorCode
@ O_KRB5_SUCCESS
@ O_KRB5_EXPECTED_NOT_NULL
@ O_KRB5_REALM_NOT_FOUND
@ O_KRB5_CONF_NOT_FOUND
#define okrb5_set_slice_from_str(slice, str)
struct OKrb5Slice kdc
struct OKrb5Slice realm
struct OKrb5Target target
struct OKrb5Slice config_path
struct OKrb5User user
void * data
struct OKrb5Slice service
struct OKrb5Slice domain
struct OKrb5Slice host_name
struct OKrb5Slice password
struct OKrb5Slice user
long int i_val
Definition nasl_tree.h:104
long int size
Definition nasl_tree.h:99
union TC::@332262321161220155002104006201360276211317150140 x
char * str_val
Definition nasl_tree.h:103
struct in6_addr * ip
Definition scanneraux.h:37
struct script_infos * script_infos