Skip to content

Commit 631e73f

Browse files
committed
Fix crash in acquiring credentials
When a creedntial store is provide 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 588d6a1 commit 631e73f

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
@@ -2629,6 +2629,38 @@ int test_NTOWF_UTF16(struct ntlm_ctx *ctx)
26292629
return test_keys("results", &expected, &result);
26302630
}
26312631

2632+
int test_ACQ_NO_NAME(void)
2633+
{
2634+
gss_cred_id_t cli_cred = GSS_C_NO_CREDENTIAL;
2635+
gss_key_value_element_desc cred_file = {
2636+
.key = GSS_NTLMSSP_CS_KEYFILE,
2637+
.value = TEST_USER_FILE
2638+
};
2639+
gss_key_value_set_desc cred_store = {
2640+
.elements = &cred_file,
2641+
.count = 1
2642+
};
2643+
uint32_t retmin, retmaj;
2644+
int ret;
2645+
2646+
retmaj = gssntlm_acquire_cred_from(&retmin, GSS_C_NO_NAME,
2647+
GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
2648+
GSS_C_INITIATE, &cred_store,
2649+
&cli_cred, NULL, NULL);
2650+
if (retmaj != GSS_S_COMPLETE) {
2651+
print_gss_error("gssntlm_acquire_cred_from(cred_store) failed!",
2652+
retmaj, retmin);
2653+
ret = EINVAL;
2654+
goto done;
2655+
}
2656+
2657+
ret = 0;
2658+
2659+
done:
2660+
gssntlm_release_cred(&retmin, &cli_cred);
2661+
return ret;
2662+
}
2663+
26322664
int main(int argc, const char *argv[])
26332665
{
26342666
struct ntlm_ctx *ctx;
@@ -2857,11 +2889,16 @@ int main(int argc, const char *argv[])
28572889
fprintf(stderr, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));
28582890
if (ret) gret++;
28592891

2860-
fprintf(stderr, "Test NTOWF iwith UTF16\n");
2892+
fprintf(stderr, "Test NTOWF with UTF16\n");
28612893
ret = test_NTOWF_UTF16(ctx);
28622894
fprintf(stderr, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));
28632895
if (ret) gret++;
28642896

2897+
fprintf(stderr, "Test Acquired cred from with no name\n");
2898+
ret = test_ACQ_NO_NAME();
2899+
fprintf(stderr, "Test: %s\n", (ret ? "FAIL":"SUCCESS"));
2900+
if (ret) gret++;
2901+
28652902
done:
28662903
ntlm_free_ctx(&ctx);
28672904
return gret;

0 commit comments

Comments
 (0)