@@ -291,30 +291,61 @@ uint32_t gssntlm_import_name_by_mech(uint32_t *minor_status,
291
291
292
292
if (gss_oid_equal (input_name_type , GSS_C_NT_HOSTBASED_SERVICE ) ||
293
293
gss_oid_equal (input_name_type , GSS_C_NT_HOSTBASED_SERVICE_X )) {
294
+ char * spn = NULL ;
295
+ char * p ;
294
296
295
297
name -> type = GSSNTLM_NAME_SERVER ;
296
298
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 );
311
302
goto done ;
312
303
}
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
+ }
317
347
}
348
+ free (spn );
318
349
set_GSSERRS (0 , GSS_S_COMPLETE );
319
350
320
351
} 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)
454
485
455
486
int gssntlm_copy_name (struct gssntlm_name * src , struct gssntlm_name * dst )
456
487
{
457
- char * dom = NULL , * usr = NULL , * srv = NULL ;
488
+ char * dom = NULL , * usr = NULL , * spn = NULL , * srv = NULL ;
458
489
int ret ;
459
490
dst -> type = src -> type ;
460
491
switch (src -> type ) {
@@ -480,6 +511,14 @@ int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst)
480
511
dst -> data .user .name = usr ;
481
512
break ;
482
513
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 ;
483
522
if (src -> data .server .name ) {
484
523
srv = strdup (src -> data .server .name );
485
524
if (!srv ) {
@@ -499,6 +538,7 @@ int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst)
499
538
if (ret ) {
500
539
safefree (dom );
501
540
safefree (usr );
541
+ safefree (spn );
502
542
safefree (srv );
503
543
}
504
544
return ret ;
@@ -560,6 +600,7 @@ void gssntlm_int_release_name(struct gssntlm_name *name)
560
600
safefree (name -> data .user .name );
561
601
break ;
562
602
case GSSNTLM_NAME_SERVER :
603
+ safefree (name -> data .server .spn );
563
604
safefree (name -> data .server .name );
564
605
break ;
565
606
}
@@ -635,7 +676,7 @@ uint32_t gssntlm_display_name(uint32_t *minor_status,
635
676
}
636
677
break ;
637
678
case GSSNTLM_NAME_SERVER :
638
- out -> value = strdup (in -> data .server .name );
679
+ out -> value = strdup (in -> data .server .spn );
639
680
if (!out -> value ) {
640
681
set_GSSERR (ENOMEM );
641
682
goto done ;
0 commit comments