Skip to content

Commit 7184fc6

Browse files
committed
Fix crash in acquiring credentials
When a credential store is provided, but no name is provided, we end up crashing by dereferencing the name. Allow the request to proceed without a name, as it may be selected out of a credential file, but if none was found, return an error. Signed-off-by: Simo Sorce <[email protected]>
1 parent 0109215 commit 7184fc6

File tree

2 files changed

+67
-26
lines changed

2 files changed

+67
-26
lines changed

src/gss_creds.c

+29-25
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,11 @@ static int get_user_file_creds(const char *filename,
161161
cred->type = GSSNTLM_CRED_USER;
162162
cred->cred.user.user.type = GSSNTLM_NAME_USER;
163163
if (dom) {
164+
free(cred->cred.user.user.data.user.domain);
164165
cred->cred.user.user.data.user.domain = strdup(dom);
165166
if (!cred->cred.user.user.data.user.domain) return ENOMEM;
166167
}
168+
free(cred->cred.user.user.data.user.name);
167169
cred->cred.user.user.data.user.name = strdup(usr);
168170
if (!cred->cred.user.user.data.user.name) return ENOMEM;
169171

@@ -235,52 +237,51 @@ static int get_creds_from_store(struct gssntlm_name *name,
235237
uint32_t i;
236238
int ret;
237239

238-
/* special case to let server creds carry a keyfile */
239-
if (name->type == GSSNTLM_NAME_SERVER) {
240-
const char *keyfile = NULL;
241-
cred->type = GSSNTLM_CRED_SERVER;
242-
ret = gssntlm_copy_name(name, &cred->cred.server.name);
243-
if (ret) return ret;
244-
for (i = 0; i < cred_store->count; i++) {
245-
if (strcmp(cred_store->elements[i].key,
246-
GSS_NTLMSSP_CS_KEYFILE) == 0) {
247-
keyfile = cred_store->elements[i].value;
240+
if (name) {
241+
/* special case to let server creds carry a keyfile */
242+
if (name->type == GSSNTLM_NAME_SERVER) {
243+
const char *keyfile = NULL;
244+
cred->type = GSSNTLM_CRED_SERVER;
245+
ret = gssntlm_copy_name(name, &cred->cred.server.name);
246+
if (ret) return ret;
247+
for (i = 0; i < cred_store->count; i++) {
248+
if (strcmp(cred_store->elements[i].key,
249+
GSS_NTLMSSP_CS_KEYFILE) == 0) {
250+
keyfile = cred_store->elements[i].value;
251+
}
248252
}
249-
}
250-
if (keyfile) {
251-
cred->cred.server.keyfile = strdup(keyfile);
252-
if (cred->cred.server.keyfile == NULL) {
253-
return errno;
253+
if (keyfile) {
254+
cred->cred.server.keyfile = strdup(keyfile);
255+
if (cred->cred.server.keyfile == NULL) {
256+
return errno;
257+
}
254258
}
259+
return 0;
255260
}
256-
return 0;
261+
262+
if (name->type != GSSNTLM_NAME_USER) return ENOENT;
263+
264+
ret = gssntlm_copy_name(name, &cred->cred.user.user);
265+
if (ret) return ret;
257266
}
258267

259268
/* so far only user options can be defined in the cred_store */
260-
if (name->type != GSSNTLM_NAME_USER) return ENOENT;
261-
262269
cred->type = GSSNTLM_CRED_USER;
263-
ret = gssntlm_copy_name(name, &cred->cred.user.user);
264-
if (ret) return ret;
265270

266271
for (i = 0; i < cred_store->count; i++) {
267272
if (strcmp(cred_store->elements[i].key, GSS_NTLMSSP_CS_DOMAIN) == 0) {
268-
/* ignore duplicates */
269-
if (cred->cred.user.user.data.user.domain) continue;
273+
free(cred->cred.user.user.data.user.domain);
270274
cred->cred.user.user.data.user.domain =
271275
strdup(cred_store->elements[i].value);
272276
if (!cred->cred.user.user.data.user.domain) return ENOMEM;
273277
}
274278
if (strcmp(cred_store->elements[i].key, GSS_NTLMSSP_CS_NTHASH) == 0) {
275-
/* ignore duplicates */
276-
if (cred->cred.user.nt_hash.length) continue;
277279
ret = hex_to_key(cred_store->elements[i].value,
278280
&cred->cred.user.nt_hash);
279281
if (ret) return ret;
280282
}
281283
if ((strcmp(cred_store->elements[i].key, GSS_NTLMSSP_CS_PASSWORD) == 0) ||
282284
(strcmp(cred_store->elements[i].key, GENERIC_CS_PASSWORD) == 0)) {
283-
if (cred->cred.user.nt_hash.length) continue;
284285
cred->cred.user.nt_hash.length = 16;
285286
ret = NTOWFv1(cred_store->elements[i].value,
286287
&cred->cred.user.nt_hash);
@@ -301,6 +302,9 @@ static int get_creds_from_store(struct gssntlm_name *name,
301302
}
302303
}
303304

305+
/* now check if a user name was found, if not error out */
306+
if (cred->cred.user.user.data.user.name == NULL) return ENOENT;
307+
304308
return 0;
305309
}
306310

tests/ntlmssptest.c

+38-1
Original file line numberDiff line numberDiff line change
@@ -2655,6 +2655,38 @@ int test_NTOWF_UTF16(struct ntlm_ctx *ctx)
26552655
return test_keys("results", &expected, &result);
26562656
}
26572657

2658+
int test_ACQ_NO_NAME(void)
2659+
{
2660+
gss_cred_id_t cli_cred = GSS_C_NO_CREDENTIAL;
2661+
gss_key_value_element_desc cred_file = {
2662+
.key = GSS_NTLMSSP_CS_KEYFILE,
2663+
.value = TEST_USER_FILE
2664+
};
2665+
gss_key_value_set_desc cred_store = {
2666+
.elements = &cred_file,
2667+
.count = 1
2668+
};
2669+
uint32_t retmin, retmaj;
2670+
int ret;
2671+
2672+
retmaj = gssntlm_acquire_cred_from(&retmin, GSS_C_NO_NAME,
2673+
GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
2674+
GSS_C_INITIATE, &cred_store,
2675+
&cli_cred, NULL, NULL);
2676+
if (retmaj != GSS_S_COMPLETE) {
2677+
print_gss_error("gssntlm_acquire_cred_from(cred_store) failed!",
2678+
retmaj, retmin);
2679+
ret = EINVAL;
2680+
goto done;
2681+
}
2682+
2683+
ret = 0;
2684+
2685+
done:
2686+
gssntlm_release_cred(&retmin, &cli_cred);
2687+
return ret;
2688+
}
2689+
26582690
int main(int argc, const char *argv[])
26592691
{
26602692
struct ntlm_ctx *ctx;
@@ -2883,11 +2915,16 @@ int main(int argc, const char *argv[])
28832915
fprintf(stderr, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));
28842916
if (ret) gret++;
28852917

2886-
fprintf(stderr, "Test NTOWF iwith UTF16\n");
2918+
fprintf(stderr, "Test NTOWF with UTF16\n");
28872919
ret = test_NTOWF_UTF16(ctx);
28882920
fprintf(stderr, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));
28892921
if (ret) gret++;
28902922

2923+
fprintf(stderr, "Test Acquired cred from with no name\n");
2924+
ret = test_ACQ_NO_NAME();
2925+
fprintf(stderr, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));
2926+
if (ret) gret++;
2927+
28912928
done:
28922929
ntlm_free_ctx(&ctx);
28932930
return gret;

0 commit comments

Comments
 (0)