Skip to content

Commit 4d3f37d

Browse files
committed
Store the full SPN within a server gssntlm_name
The SPN is used to fill the Traget Name Attribute in the Target Info array. This means we need to preserver the SPN as passed to us (via conversion from a GSS Name). This patch adds an spn field to the server union part of gssntlm_name structure. Signed-off-by: Simo Sorce <[email protected]>
1 parent 1cbc124 commit 4d3f37d

File tree

2 files changed

+62
-20
lines changed

2 files changed

+62
-20
lines changed

src/gss_names.c

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -291,30 +291,61 @@ uint32_t gssntlm_import_name_by_mech(uint32_t *minor_status,
291291

292292
if (gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE) ||
293293
gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE_X)) {
294+
char *spn = NULL;
295+
char *p;
294296

295297
name->type = GSSNTLM_NAME_SERVER;
296298

297-
retmaj = string_split(&retmin, '@',
298-
input_name_buffer->value,
299-
input_name_buffer->length,
300-
NULL, &name->data.server.name);
301-
if ((retmaj == GSS_S_COMPLETE) ||
302-
(retmaj != GSS_S_UNAVAILABLE)) {
303-
goto done;
304-
}
305-
306-
/* no seprator, assume only service is provided and try to source
307-
* the local host name */
308-
retmin = gethostname(hostname, HOST_NAME_MAX);
309-
if (retmin) {
310-
set_GSSERR(retmin);
299+
spn = strndup(input_name_buffer->value, input_name_buffer->length);
300+
if (!spn) {
301+
set_GSSERR(ENOMEM);
311302
goto done;
312303
}
313-
hostname[HOST_NAME_MAX] = '\0';
314-
name->data.server.name = strdup(hostname);
315-
if (!name->data.server.name) {
316-
set_GSSERR(ENOMEM);
304+
p = memchr(spn, '@', input_name_buffer->length);
305+
if (p) {
306+
/* Windows expects a SPN not a GSS Name */
307+
*p = '/';
308+
name->data.server.spn = spn;
309+
spn = NULL;
310+
name->data.server.name = strdup(p + 1);
311+
if (!name->data.server.name) {
312+
free(spn);
313+
set_GSSERR(ENOMEM);
314+
goto done;
315+
}
316+
} else {
317+
size_t l, r;
318+
/* no seprator, assume only service is provided and try to
319+
* source the local host name */
320+
retmin = gethostname(hostname, HOST_NAME_MAX);
321+
if (retmin) {
322+
free(spn);
323+
set_GSSERR(retmin);
324+
goto done;
325+
}
326+
hostname[HOST_NAME_MAX] = '\0';
327+
/* spn = <service> + </> + <hostname> + <\0> */
328+
l = strlen(spn) + 1 + strlen(hostname) + 1;
329+
name->data.server.spn = malloc(l);
330+
if (!name->data.server.spn) {
331+
free(spn);
332+
set_GSSERR(ENOMEM);
333+
goto done;
334+
}
335+
r = snprintf(name->data.server.spn, l, "%s/%s", spn, hostname);
336+
if (r != l - 1) {
337+
free(spn);
338+
set_GSSERR(ENOMEM);
339+
goto done;
340+
}
341+
name->data.server.name = strdup(hostname);
342+
if (!name->data.server.name) {
343+
free(spn);
344+
set_GSSERR(ENOMEM);
345+
goto done;
346+
}
317347
}
348+
free(spn);
318349
set_GSSERRS(0, GSS_S_COMPLETE);
319350

320351
} else if (gss_oid_equal(input_name_type, GSS_C_NT_USER_NAME)) {
@@ -454,7 +485,7 @@ void gssntlm_release_attrs(struct gssntlm_name_attribute **attrs)
454485

455486
int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst)
456487
{
457-
char *dom = NULL, *usr = NULL, *srv = NULL;
488+
char *dom = NULL, *usr = NULL, *spn = NULL, *srv = NULL;
458489
int ret;
459490
dst->type = src->type;
460491
switch (src->type) {
@@ -480,6 +511,14 @@ int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst)
480511
dst->data.user.name = usr;
481512
break;
482513
case GSSNTLM_NAME_SERVER:
514+
if (src->data.server.spn) {
515+
spn = strdup(src->data.server.spn);
516+
if (!spn) {
517+
ret = ENOMEM;
518+
goto done;
519+
}
520+
}
521+
dst->data.server.spn = spn;
483522
if (src->data.server.name) {
484523
srv = strdup(src->data.server.name);
485524
if (!srv) {
@@ -499,6 +538,7 @@ int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst)
499538
if (ret) {
500539
safefree(dom);
501540
safefree(usr);
541+
safefree(spn);
502542
safefree(srv);
503543
}
504544
return ret;
@@ -560,6 +600,7 @@ void gssntlm_int_release_name(struct gssntlm_name *name)
560600
safefree(name->data.user.name);
561601
break;
562602
case GSSNTLM_NAME_SERVER:
603+
safefree(name->data.server.spn);
563604
safefree(name->data.server.name);
564605
break;
565606
}
@@ -635,7 +676,7 @@ uint32_t gssntlm_display_name(uint32_t *minor_status,
635676
}
636677
break;
637678
case GSSNTLM_NAME_SERVER:
638-
out->value = strdup(in->data.server.name);
679+
out->value = strdup(in->data.server.spn);
639680
if (!out->value) {
640681
set_GSSERR(ENOMEM);
641682
goto done;

src/gss_ntlmssp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ struct gssntlm_name {
5959
char *name;
6060
} user;
6161
struct {
62+
char *spn;
6263
char *name;
6364
} server;
6465
} data;

0 commit comments

Comments
 (0)