Skip to content

Commit c0a0216

Browse files
committed
Add gssspi_mech_invoke method to turn on debugging
This allows to set a file of own chosing as well as turn on and off debugging as needed. Mostly thread safe, and applies to all threads at once. There is a very small window for a race condition where a thread modifies the debug_fd at the same time another thread is actually trying to print a debug message. In order to handle this case without the performance hit of a mutex on every debug message, we change the implementation to use file descriptors instead. printing to a closed file descriptor or to a -1 file descriptor returns an error but does not crash the process as it happens when a file stream is NULL or pointing to freed memory. Signed-off-by: Simo Sorce <[email protected]>
1 parent 9787e63 commit c0a0216

File tree

8 files changed

+191
-10
lines changed

8 files changed

+191
-10
lines changed

src/debug.c

+96-6
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,123 @@
11
/* Copyright (C) 2014 GSS-NTLMSSP contributors, see COPYING for license */
22

33
#define _GNU_SOURCE
4+
#include <errno.h>
5+
#include <fcntl.h>
6+
#include <limits.h>
7+
#include <pthread.h>
48
#include <stdarg.h>
59
#include <stdbool.h>
610
#include <stdio.h>
711
#include <stdlib.h>
12+
#include <string.h>
13+
#include <sys/stat.h>
14+
#include <sys/types.h>
15+
#include <unistd.h>
816

17+
#include "gssapi_ntlmssp.h"
18+
19+
#define OPEN_FLAGS O_WRONLY | O_CREAT | O_APPEND| O_CLOEXEC
20+
#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
21+
22+
static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
923
bool gssntlm_debug_initialized = false;
10-
bool gssntlm_debug_enabled = false;
11-
static FILE *debug_fd = NULL;
24+
int gssntlm_debug_fd = -1;
1225

1326
void gssntlm_debug_init(void)
1427
{
1528
char *env;
1629

30+
if (gssntlm_debug_initialized) return;
31+
32+
pthread_mutex_lock(&debug_mutex);
33+
1734
env = secure_getenv("GSSNTLMSSP_DEBUG");
1835
if (env) {
19-
debug_fd = fopen(env, "a");
20-
if (debug_fd) gssntlm_debug_enabled = true;
36+
gssntlm_debug_fd = open(env, OPEN_FLAGS, 0660);
2137
}
2238
gssntlm_debug_initialized = true;
39+
40+
pthread_mutex_unlock(&debug_mutex);
2341
}
2442

2543
void gssntlm_debug_printf(const char *fmt, ...)
2644
{
2745
va_list ap;
2846

47+
if (gssntlm_debug_fd == -1) return;
48+
2949
va_start(ap, fmt);
30-
vfprintf(debug_fd, fmt, ap);
50+
vdprintf(gssntlm_debug_fd, fmt, ap);
3151
va_end(ap);
32-
fflush(debug_fd);
52+
fdatasync(gssntlm_debug_fd);
53+
}
54+
55+
static int gssntlm_debug_enable(const char *filename)
56+
{
57+
int old_debug_fd = gssntlm_debug_fd;
58+
int new_debug_fd = -1;
59+
int ret = 0;
60+
61+
pthread_mutex_lock(&debug_mutex);
62+
63+
gssntlm_debug_initialized = true;
64+
65+
new_debug_fd = open(filename, OPEN_FLAGS, 0660);
66+
if (new_debug_fd == -1) {
67+
ret = errno;
68+
}
69+
70+
gssntlm_debug_fd = new_debug_fd;
71+
72+
if (old_debug_fd != -1) {
73+
close(old_debug_fd);
74+
}
75+
76+
pthread_mutex_unlock(&debug_mutex);
77+
78+
return ret;
79+
}
80+
81+
static int gssntlm_debug_disable(void)
82+
{
83+
int old_debug_fd = gssntlm_debug_fd;
84+
int ret = 0;
85+
86+
pthread_mutex_lock(&debug_mutex);
87+
88+
gssntlm_debug_fd = -1;
89+
90+
if (old_debug_fd != -1) {
91+
ret = close(old_debug_fd);
92+
}
93+
94+
pthread_mutex_unlock(&debug_mutex);
95+
96+
return ret;
97+
}
98+
99+
gss_OID_desc gssntlm_debug_oid = {
100+
GSS_NTLMSSP_DEBUG_OID_LENGTH,
101+
discard_const(GSS_NTLMSSP_DEBUG_OID_STRING)
102+
};
103+
104+
int gssntlm_debug_invoke(gss_buffer_t value)
105+
{
106+
char filename[PATH_MAX] = { 0 };
107+
108+
if (value->length > PATH_MAX - 1) {
109+
return EINVAL;
110+
}
111+
112+
if ((value->length != 0) &&
113+
(((char *)value->value)[0] != '\0')) {
114+
memcpy(filename, value->value, value->length);
115+
filename[value->length] = '\0';
116+
}
117+
118+
if (filename[0] == '\0') {
119+
return gssntlm_debug_disable();
120+
}
121+
122+
return gssntlm_debug_enable(filename);
33123
}

src/debug.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
#include <stdbool.h>
77
#include <time.h>
88

9+
extern gss_OID_desc gssntlm_debug_oid;
910
extern bool gssntlm_debug_initialized;
10-
extern bool gssntlm_debug_enabled;
11+
extern int gssntlm_debug_fd;
1112

1213
void gssntlm_debug_init(void);
1314
void gssntlm_debug_printf(const char *fmt, ...);
@@ -23,7 +24,7 @@ static inline int debug_gss_errors(const char *function,
2324
if (unlikely(gssntlm_debug_initialized == false)) {
2425
gssntlm_debug_init();
2526
}
26-
if (unlikely(gssntlm_debug_enabled == true)) {
27+
if (unlikely(gssntlm_debug_fd != -1)) {
2728
gssntlm_debug_printf("[%ld] %s: %s() @ %s:%u [%u:%u]\n",
2829
(long)time(NULL),
2930
GSS_ERROR(maj) ? "ERROR" : "ALLOK",
@@ -34,4 +35,6 @@ static inline int debug_gss_errors(const char *function,
3435
#define DEBUG_GSS_ERRORS(maj, min) \
3536
debug_gss_errors(__FUNCTION__, __FILE__, __LINE__, maj, min)
3637

38+
int gssntlm_debug_invoke(gss_buffer_t value);
39+
3740
#endif /* _GSSNTLMSSP_DEBUG_H_ */

src/gss_ntlmssp.c

+33
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,36 @@ int gssntlm_get_lm_compatibility_level(void)
178178
/* use 3 by default for better compatibility */
179179
return 3;
180180
}
181+
182+
uint32_t gssntlm_mech_invoke(uint32_t *minor_status,
183+
const gss_OID desired_mech,
184+
const gss_OID desired_object,
185+
gss_buffer_t value)
186+
{
187+
uint32_t retmaj = GSS_S_COMPLETE;
188+
uint32_t retmin = 0;
189+
190+
if (minor_status == NULL) {
191+
return GSS_S_CALL_INACCESSIBLE_WRITE;
192+
}
193+
194+
if (desired_mech != GSS_C_NO_OID &&
195+
!gss_oid_equal(desired_mech, &gssntlm_oid)) {
196+
return GSSERRS(0, GSS_S_BAD_MECH);
197+
}
198+
199+
if (desired_object == GSS_C_NO_OID) {
200+
return GSSERRS(0, GSS_S_CALL_INACCESSIBLE_READ);
201+
}
202+
203+
if (!gss_oid_equal(desired_object, &gssntlm_debug_oid)) {
204+
return GSSERRS(EINVAL, GSS_S_UNAVAILABLE);
205+
}
206+
207+
retmin = gssntlm_debug_invoke(value);
208+
if (retmin != 0) {
209+
retmaj = GSS_S_UNAVAILABLE;
210+
}
211+
212+
return GSSERR();
213+
}

src/gss_ntlmssp.h

+5
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ uint32_t gssntlm_context_is_valid(struct gssntlm_ctx *ctx,
176176

177177
int gssntlm_get_lm_compatibility_level(void);
178178

179+
uint32_t gssntlm_mech_invoke(uint32_t *minor_status,
180+
const gss_OID desired_mech,
181+
const gss_OID desired_object,
182+
gss_buffer_t value);
183+
179184
void gssntlm_int_release_name(struct gssntlm_name *name);
180185
void gssntlm_int_release_cred(struct gssntlm_cred *cred);
181186

src/gss_spi.c

+9
Original file line numberDiff line numberDiff line change
@@ -443,3 +443,12 @@ OM_uint32 gss_inquire_attrs_for_mech(OM_uint32 *minor_status,
443443
return gssntlm_inquire_attrs_for_mech(minor_status, mech_oid, mech_attrs,
444444
known_mech_attrs);
445445
}
446+
447+
OM_uint32 gssspi_mech_invoke(OM_uint32 *minor_status,
448+
const gss_OID desired_mech,
449+
const gss_OID desired_object,
450+
gss_buffer_t value)
451+
{
452+
return gssntlm_mech_invoke(minor_status, desired_mech, desired_object,
453+
value);
454+
}

src/gssapi_ntlmssp.h

+8
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ extern "C" {
5353
#define GSS_NTLMSSP_RESET_CRYPTO_OID_STRING GSS_NTLMSSP_BASE_OID_STRING "\x03"
5454
#define GSS_NTLMSSP_RESET_CRYPTO_OID_LENGTH GSS_NTLMSSP_BASE_OID_LENGTH + 1
5555

56+
/* Debug OID for mech_invoke
57+
* Use this with gsspi_mech_invoke, to pass a file name and enable debugging.
58+
*/
59+
#define GSS_NTLMSSP_DEBUG_OID_STRING GSS_NTLMSSP_BASE_OID_STRING "\x04"
60+
#define GSS_NTLMSSP_DEBUG_OID_LENGTH GSS_NTLMSSP_BASE_OID_LENGTH + 1
61+
62+
63+
5664
#define GSS_NTLMSSP_CS_DOMAIN "ntlmssp_domain"
5765
#define GSS_NTLMSSP_CS_NTHASH "ntlmssp_nthash"
5866
#define GSS_NTLMSSP_CS_PASSWORD "ntlmssp_password"

tests/env2.sh

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
EXAMPLES=$(dirname "$0")/../examples
44

5+
export NTLMSSP_TEST_DEBUG="tests-trace-2.log"
6+
57
export NTLM_USER_FILE="${EXAMPLES}/test_user_file3.txt"
68
export TEST_USER_NAME="TESTDOM\\testuser"
79
./ntlmssptest
10+
11+
if [ ! -f "tests-trace-2.log" ]; then
12+
echo "Debug trace file not found!"
13+
exit -1
14+
fi

tests/ntlmssptest.c

+28-2
Original file line numberDiff line numberDiff line change
@@ -2790,14 +2790,40 @@ int test_import_name(void)
27902790
return ret;
27912791
}
27922792

2793+
int test_debug(void)
2794+
{
2795+
char *test_env;
2796+
uint32_t maj, min;
2797+
2798+
test_env = getenv("NTLMSSP_TEST_DEBUG");
2799+
if (test_env) {
2800+
fprintf(stderr, "%s\n", test_env);
2801+
gss_buffer_desc val = { strlen(test_env), test_env };
2802+
maj = gssntlm_mech_invoke(&min, discard_const(&gssntlm_oid),
2803+
discard_const(&gssntlm_debug_oid), &val);
2804+
if (maj != GSS_S_COMPLETE) {
2805+
fprintf(stderr, "%d %d\n", maj, min);
2806+
return 1;
2807+
}
2808+
return 0;
2809+
}
2810+
2811+
/* enable trace debugging by default in tests */
2812+
setenv("GSSNTLMSSP_DEBUG", "tests-trace.log", 0);
2813+
2814+
return 0;
2815+
}
2816+
27932817
int main(int argc, const char *argv[])
27942818
{
27952819
struct ntlm_ctx *ctx;
27962820
int gret = 0;
27972821
int ret;
27982822

2799-
/* enable trace debugging by dfault in tests */
2800-
setenv("GSSNTLMSSP_DEBUG", "tests-trace.log", 0);
2823+
fprintf(stderr, "Test setup debug\n");
2824+
ret = test_debug();
2825+
fprintf(stderr, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));
2826+
if (ret) gret++;
28012827

28022828
fprintf(stderr, "Test errors\n");
28032829
ret = test_Errors();

0 commit comments

Comments
 (0)