Skip to content

Commit 313f32b

Browse files
committed
Add client side anonymous authentication
Signed-off-by: Simo Sorce <[email protected]>
1 parent e1a5f27 commit 313f32b

File tree

5 files changed

+112
-81
lines changed

5 files changed

+112
-81
lines changed

src/gss_auth.c

+84-69
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,55 @@ uint32_t gssntlm_cli_auth(uint32_t *minor_status,
2121
struct ntlm_buffer auth_mic = { NULL, 16 };
2222
uint8_t micbuf[16];
2323
struct ntlm_buffer mic = { micbuf, 16 };
24+
char *username;
25+
char *domain;
26+
bool ext_sec;
2427
bool add_mic = false;
2528
bool key_exch;
2629
uint32_t retmaj;
2730
uint32_t retmin;
2831

32+
ext_sec = (in_flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY);
33+
2934
switch (cred->type) {
3035

36+
case GSSNTLM_CRED_EXTERNAL:
37+
retmin = external_cli_auth(ctx, cred, in_flags, input_chan_bindings);
38+
if (retmin) {
39+
set_GSSERR(retmin);
40+
goto done;
41+
}
42+
set_GSSERRS(0, GSS_S_COMPLETE);
43+
return GSSERR();
44+
45+
case GSSNTLM_CRED_ANON:
46+
47+
/* Anonymous auth, empty responses */
48+
if (!(ctx->gss_flags & GSS_C_ANON_FLAG)) {
49+
set_GSSERR(EINVAL);
50+
goto done;
51+
}
52+
53+
domain = NULL;
54+
username = NULL;
55+
memset(&nt_chal_resp, 0, sizeof(nt_chal_resp));
56+
lm_chal_resp.data = malloc(1);
57+
if (!lm_chal_resp.data) {
58+
set_GSSERR(ENOMEM);
59+
goto done;
60+
}
61+
lm_chal_resp.data[0] = 0;
62+
lm_chal_resp.length = 1;
63+
64+
memset(key_exchange_key.data, 0, 16);
65+
break;
66+
3167
case GSSNTLM_CRED_USER:
3268

33-
if (ctx->gss_flags & GSS_C_ANON_FLAG) {
34-
/* Anonymous auth, empty responses */
35-
memset(&nt_chal_resp, 0, sizeof(nt_chal_resp));
36-
lm_chal_resp.data = malloc(1);
37-
if (!lm_chal_resp.data) {
38-
set_GSSERR(ENOMEM);
39-
goto done;
40-
}
41-
lm_chal_resp.data[0] = 0;
42-
lm_chal_resp.length = 1;
69+
domain = cred->cred.user.user.data.user.domain;
70+
username = cred->cred.user.user.data.user.name;
4371

44-
} else if (gssntlm_sec_v2_ok(ctx)) {
72+
if (gssntlm_sec_v2_ok(ctx)) {
4573

4674
/* ### NTLMv2 ### */
4775
uint8_t client_chal[8];
@@ -111,9 +139,7 @@ uint32_t gssntlm_cli_auth(uint32_t *minor_status,
111139

112140
/* NTLMv2 Key */
113141
retmin = NTOWFv2(ctx->ntlm, &cred->cred.user.nt_hash,
114-
cred->cred.user.user.data.user.name,
115-
cred->cred.user.user.data.user.domain,
116-
&ntlmv2_key);
142+
username, domain, &ntlmv2_key);
117143
if (retmin) {
118144
set_GSSERR(retmin);
119145
goto done;
@@ -160,7 +186,6 @@ uint32_t gssntlm_cli_auth(uint32_t *minor_status,
160186
struct ntlm_buffer cli_chal = { client_chal, 8 };
161187
struct ntlm_key session_base_key = { .length = 16 };
162188
bool NoLMResponseNTLMv1 = !gssntlm_sec_lm_ok(ctx);
163-
bool ext_sec;
164189

165190
nt_chal_resp.length = 24;
166191
nt_chal_resp.data = calloc(1, nt_chal_resp.length);
@@ -178,8 +203,6 @@ uint32_t gssntlm_cli_auth(uint32_t *minor_status,
178203
goto done;
179204
}
180205

181-
ext_sec = (in_flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY);
182-
183206
retmin = ntlm_compute_nt_response(&cred->cred.user.nt_hash,
184207
ext_sec, ctx->server_chal,
185208
client_chal, &nt_chal_resp);
@@ -219,77 +242,69 @@ uint32_t gssntlm_cli_auth(uint32_t *minor_status,
219242
}
220243
}
221244

222-
key_exch = (in_flags & NTLMSSP_NEGOTIATE_KEY_EXCH);
223-
224-
retmin = ntlm_exported_session_key(&key_exchange_key, key_exch,
225-
&ctx->exported_session_key);
226-
if (retmin) {
227-
set_GSSERR(retmin);
228-
goto done;
229-
}
245+
break;
230246

231-
if (key_exch) {
232-
retmin = ntlm_encrypted_session_key(&key_exchange_key,
233-
&ctx->exported_session_key,
234-
&encrypted_random_session_key);
235-
if (retmin) {
236-
set_GSSERR(retmin);
237-
goto done;
238-
}
239-
}
247+
default:
248+
set_GSSERR(ERR_NOUSRCRED);
249+
goto done;
250+
}
240251

241-
/* in_flags all verified, assign as current flags */
242-
ctx->neg_flags |= in_flags;
252+
key_exch = (in_flags & NTLMSSP_NEGOTIATE_KEY_EXCH);
243253

244-
enc_sess_key.data = encrypted_random_session_key.data;
245-
enc_sess_key.length = encrypted_random_session_key.length;
254+
retmin = ntlm_exported_session_key(&key_exchange_key, key_exch,
255+
&ctx->exported_session_key);
256+
if (retmin) {
257+
set_GSSERR(retmin);
258+
goto done;
259+
}
246260

247-
retmin = ntlm_encode_auth_msg(ctx->ntlm, ctx->neg_flags,
248-
&lm_chal_resp, &nt_chal_resp,
249-
cred->cred.user.user.data.user.domain,
250-
cred->cred.user.user.data.user.name,
251-
ctx->workstation, &enc_sess_key,
252-
add_mic ? &auth_mic : NULL,
253-
&ctx->auth_msg);
261+
if (key_exch) {
262+
retmin = ntlm_encrypted_session_key(&key_exchange_key,
263+
&ctx->exported_session_key,
264+
&encrypted_random_session_key);
254265
if (retmin) {
255266
set_GSSERR(retmin);
256267
goto done;
257268
}
269+
}
258270

259-
/* Now we need to calculate the MIC, because the MIC is part of the
260-
* message it protects, ntlm_encode_auth_msg() always add a zeroeth
261-
* buffer, however it returns in data_mic the pointer to the actual
262-
* area in the auth_msg that points at the mic, so we can backfill */
263-
if (add_mic) {
264-
retmin = ntlm_mic(&ctx->exported_session_key, &ctx->nego_msg,
265-
&ctx->chal_msg, &ctx->auth_msg, &mic);
266-
if (retmin) {
267-
set_GSSERR(retmin);
268-
goto done;
269-
}
270-
/* now that we have the mic, copy it into the auth message */
271-
memcpy(auth_mic.data, mic.data, 16);
271+
/* in_flags all verified, assign as current flags */
272+
ctx->neg_flags |= in_flags;
272273

273-
/* Make sure SPNEGO gets to know it has to add mechlistMIC too */
274-
ctx->int_flags |= NTLMSSP_CTX_FLAG_AUTH_WITH_MIC;
275-
}
274+
enc_sess_key.data = encrypted_random_session_key.data;
275+
enc_sess_key.length = encrypted_random_session_key.length;
276276

277-
set_GSSERRS(0, GSS_S_COMPLETE);
278-
break;
277+
retmin = ntlm_encode_auth_msg(ctx->ntlm, ctx->neg_flags,
278+
&lm_chal_resp, &nt_chal_resp,
279+
domain, username,
280+
ctx->workstation, &enc_sess_key,
281+
add_mic ? &auth_mic : NULL,
282+
&ctx->auth_msg);
283+
if (retmin) {
284+
set_GSSERR(retmin);
285+
goto done;
286+
}
279287

280-
case GSSNTLM_CRED_EXTERNAL:
281-
retmin = external_cli_auth(ctx, cred, in_flags, input_chan_bindings);
288+
/* Now we need to calculate the MIC, because the MIC is part of the
289+
* message it protects, ntlm_encode_auth_msg() always add a zeroeth
290+
* buffer, however it returns in data_mic the pointer to the actual
291+
* area in the auth_msg that points at the mic, so we can backfill */
292+
if (add_mic) {
293+
retmin = ntlm_mic(&ctx->exported_session_key, &ctx->nego_msg,
294+
&ctx->chal_msg, &ctx->auth_msg, &mic);
282295
if (retmin) {
283296
set_GSSERR(retmin);
284297
goto done;
285298
}
286-
set_GSSERRS(0, GSS_S_COMPLETE);
287-
break;
299+
/* now that we have the mic, copy it into the auth message */
300+
memcpy(auth_mic.data, mic.data, 16);
288301

289-
default:
290-
set_GSSERR(ERR_NOUSRCRED);
302+
/* Make sure SPNEGO gets to know it has to add mechlistMIC too */
303+
ctx->int_flags |= NTLMSSP_CTX_FLAG_AUTH_WITH_MIC;
291304
}
292305

306+
set_GSSERRS(0, GSS_S_COMPLETE);
307+
293308
done:
294309
ntlm_free_buffer_data(&client_target_info);
295310
ntlm_free_buffer_data(&nt_chal_resp);

src/gss_creds.c

+8
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,14 @@ uint32_t gssntlm_acquire_cred_from(uint32_t *minor_status,
430430
}
431431

432432
if (cred_usage == GSS_C_INITIATE) {
433+
if (name != NULL && name->type == GSSNTLM_NAME_ANON) {
434+
cred->type = GSSNTLM_CRED_ANON;
435+
cred->cred.anon.dummy = 0;
436+
retmin = 0;
437+
retmaj = 0;
438+
goto done;
439+
}
440+
433441
if (name != NULL && name->type != GSSNTLM_NAME_USER) {
434442
set_GSSERRS(ERR_NOUSRNAME, GSS_S_BAD_NAMETYPE);
435443
goto done;

src/gss_names.c

+1
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ static uint32_t make_ma_oid_set(uint32_t *minor_status, gss_OID_set *ma_set,
761761
GSS_C_MA_OOS_DET,
762762
GSS_C_MA_CBINDINGS,
763763
GSS_C_MA_CTX_TRANS,
764+
GSS_C_MA_AUTH_INIT_ANON,
764765
NULL
765766
};
766767
uint32_t maj = 0;

src/gss_sec_ctx.c

+18-11
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status,
4040
{
4141
struct gssntlm_ctx *ctx;
4242
struct gssntlm_name *server = NULL;
43+
struct gssntlm_name *anonymous = NULL;
4344
struct gssntlm_cred *cred = NULL;
4445
char *computer_name = NULL;
4546
char *nb_computer_name = NULL;
@@ -79,16 +80,16 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status,
7980

8081
if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) {
8182
if (req_flags & GSS_C_ANON_FLAG) {
82-
set_GSSERRS(ERR_NOARG, GSS_S_UNAVAILABLE);
83-
goto done;
84-
} else {
85-
retmaj = gssntlm_acquire_cred(&retmin,
86-
NULL, time_req,
87-
NULL, GSS_C_INITIATE,
88-
(gss_cred_id_t *)&cred,
89-
NULL, time_rec);
83+
retmaj = gssntlm_import_name(&retmin, NULL, GSS_C_NT_ANONYMOUS,
84+
(gss_name_t *)&anonymous);
9085
if (retmaj) goto done;
9186
}
87+
retmaj = gssntlm_acquire_cred(&retmin,
88+
(gss_name_t)anonymous, time_req,
89+
NULL, GSS_C_INITIATE,
90+
(gss_cred_id_t *)&cred,
91+
NULL, time_rec);
92+
if (retmaj) goto done;
9293
} else {
9394
cred = (struct gssntlm_cred *)claimant_cred_handle;
9495
if (cred->type != GSSNTLM_CRED_USER &&
@@ -107,8 +108,13 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status,
107108
goto done;
108109
}
109110

110-
retmin = gssntlm_copy_name(&cred->cred.user.user,
111-
&ctx->source_name);
111+
if (req_flags & GSS_C_ANON_FLAG) {
112+
retmin = gssntlm_copy_name(anonymous,
113+
&ctx->source_name);
114+
} else {
115+
retmin = gssntlm_copy_name(&cred->cred.user.user,
116+
&ctx->source_name);
117+
}
112118
if (retmin) {
113119
set_GSSERR(retmin);
114120
goto done;
@@ -388,7 +394,7 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status,
388394
* negotiated flags */
389395
ctx->neg_flags &= in_flags;
390396

391-
retmaj = gssntlm_cli_auth(&retmin, ctx, cred, &target_info,
397+
retmaj = gssntlm_cli_auth(&retmin, ctx, cred, &target_info,
392398
in_flags, input_chan_bindings);
393399
if (retmaj) goto done;
394400

@@ -441,6 +447,7 @@ uint32_t gssntlm_init_sec_context(uint32_t *minor_status,
441447
gssntlm_release_cred(&tmpmin, (gss_cred_id_t *)&cred);
442448
}
443449
gssntlm_release_name(&tmpmin, (gss_name_t *)&client_name);
450+
gssntlm_release_name(&tmpmin, (gss_name_t *)&anonymous);
444451
safefree(computer_name);
445452
safefree(nb_computer_name);
446453
safefree(nb_domain_name);

tests/ntlmssptest.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2181,7 +2181,7 @@ int test_gssapi_rfc5587(void)
21812181
return EINVAL;
21822182
}
21832183

2184-
if (mech_attrs->count != 9) {
2184+
if (mech_attrs->count != 10) {
21852185
fprintf(stderr, "expected 9 mech_attr oids, got %lu\n",
21862186
mech_attrs->count);
21872187
return EINVAL;

0 commit comments

Comments
 (0)