1
- /* Copyright 2013 Simo Sorce <[email protected] >, see COPYING for license */
1
+ /* Copyright 2013-2022 Simo Sorce <[email protected] >, see COPYING for license */
2
2
3
3
#define _GNU_SOURCE
4
4
@@ -266,9 +266,6 @@ uint32_t gssntlm_import_name_by_mech(uint32_t *minor_status,
266
266
gss_OID input_name_type ,
267
267
gss_name_t * output_name )
268
268
{
269
- char hostname [HOST_NAME_MAX + 1 ] = { 0 };
270
- char struid [12 ] = { 0 };
271
- uid_t uid ;
272
269
struct gssntlm_name * name = NULL ;
273
270
uint32_t retmaj ;
274
271
uint32_t retmin ;
@@ -291,30 +288,74 @@ uint32_t gssntlm_import_name_by_mech(uint32_t *minor_status,
291
288
292
289
if (gss_oid_equal (input_name_type , GSS_C_NT_HOSTBASED_SERVICE ) ||
293
290
gss_oid_equal (input_name_type , GSS_C_NT_HOSTBASED_SERVICE_X )) {
291
+ char * spn = NULL ;
292
+ char * p = NULL ;
294
293
295
294
name -> type = GSSNTLM_NAME_SERVER ;
296
295
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 ;
296
+ if (input_name_buffer -> length > 0 ) {
297
+ spn = strndup (input_name_buffer -> value , input_name_buffer -> length );
298
+ if (!spn ) {
299
+ set_GSSERR (ENOMEM );
300
+ goto done ;
301
+ }
302
+ p = memchr (spn , '@' , input_name_buffer -> length );
303
+ if (p && input_name_buffer -> length == 1 ) {
304
+ free (spn );
305
+ spn = p = NULL ;
306
+ }
304
307
}
305
308
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 );
311
- goto done ;
312
- }
313
- hostname [HOST_NAME_MAX ] = '\0' ;
314
- name -> data .server .name = strdup (hostname );
315
- if (!name -> data .server .name ) {
316
- set_GSSERR (ENOMEM );
309
+ if (p ) {
310
+ /* Windows expects a SPN not a GSS Name */
311
+ if (p != spn ) {
312
+ * p = '/' ;
313
+ name -> data .server .spn = spn ;
314
+ spn = NULL ;
315
+ }
316
+ p += 1 ;
317
+ name -> data .server .name = strdup (p );
318
+ if (!name -> data .server .name ) {
319
+ free (spn );
320
+ set_GSSERR (ENOMEM );
321
+ goto done ;
322
+ }
323
+ } else {
324
+ char hostname [HOST_NAME_MAX + 1 ] = { 0 };
325
+ size_t l , r ;
326
+ /* no seprator, assume only service is provided and try to
327
+ * source the local host name */
328
+ retmin = gethostname (hostname , HOST_NAME_MAX );
329
+ if (retmin ) {
330
+ free (spn );
331
+ set_GSSERR (retmin );
332
+ goto done ;
333
+ }
334
+ hostname [HOST_NAME_MAX ] = '\0' ;
335
+ if (spn != NULL ) {
336
+ /* spn = <service> + </> + <hostname> + <\0> */
337
+ l = strlen (spn ) + 1 + strlen (hostname ) + 1 ;
338
+ name -> data .server .spn = malloc (l );
339
+ if (!name -> data .server .spn ) {
340
+ free (spn );
341
+ set_GSSERR (ENOMEM );
342
+ goto done ;
343
+ }
344
+ r = snprintf (name -> data .server .spn , l , "%s/%s" , spn , hostname );
345
+ if (r != l - 1 ) {
346
+ free (spn );
347
+ set_GSSERR (ENOMEM );
348
+ goto done ;
349
+ }
350
+ }
351
+ name -> data .server .name = strdup (hostname );
352
+ if (!name -> data .server .name ) {
353
+ free (spn );
354
+ set_GSSERR (ENOMEM );
355
+ goto done ;
356
+ }
317
357
}
358
+ free (spn );
318
359
set_GSSERRS (0 , GSS_S_COMPLETE );
319
360
320
361
} else if (gss_oid_equal (input_name_type , GSS_C_NT_USER_NAME )) {
@@ -326,13 +367,16 @@ uint32_t gssntlm_import_name_by_mech(uint32_t *minor_status,
326
367
& name -> data .user .domain ,
327
368
& name -> data .user .name );
328
369
} else if (gss_oid_equal (input_name_type , GSS_C_NT_MACHINE_UID_NAME )) {
370
+ uid_t uid ;
329
371
330
372
name -> type = GSSNTLM_NAME_USER ;
331
373
name -> data .user .domain = NULL ;
332
374
333
375
uid = * (uid_t * )input_name_buffer -> value ;
334
376
retmaj = uid_to_name (& retmin , uid , & name -> data .user .name );
335
377
} else if (gss_oid_equal (input_name_type , GSS_C_NT_STRING_UID_NAME )) {
378
+ char struid [12 ] = { 0 };
379
+ uid_t uid ;
336
380
337
381
name -> type = GSSNTLM_NAME_USER ;
338
382
name -> data .user .domain = NULL ;
@@ -454,7 +498,7 @@ void gssntlm_release_attrs(struct gssntlm_name_attribute **attrs)
454
498
455
499
int gssntlm_copy_name (struct gssntlm_name * src , struct gssntlm_name * dst )
456
500
{
457
- char * dom = NULL , * usr = NULL , * srv = NULL ;
501
+ char * dom = NULL , * usr = NULL , * spn = NULL , * srv = NULL ;
458
502
int ret ;
459
503
dst -> type = src -> type ;
460
504
switch (src -> type ) {
@@ -480,6 +524,14 @@ int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst)
480
524
dst -> data .user .name = usr ;
481
525
break ;
482
526
case GSSNTLM_NAME_SERVER :
527
+ if (src -> data .server .spn ) {
528
+ spn = strdup (src -> data .server .spn );
529
+ if (!spn ) {
530
+ ret = ENOMEM ;
531
+ goto done ;
532
+ }
533
+ }
534
+ dst -> data .server .spn = spn ;
483
535
if (src -> data .server .name ) {
484
536
srv = strdup (src -> data .server .name );
485
537
if (!srv ) {
@@ -499,6 +551,7 @@ int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst)
499
551
if (ret ) {
500
552
safefree (dom );
501
553
safefree (usr );
554
+ safefree (spn );
502
555
safefree (srv );
503
556
}
504
557
return ret ;
@@ -560,6 +613,7 @@ void gssntlm_int_release_name(struct gssntlm_name *name)
560
613
safefree (name -> data .user .name );
561
614
break ;
562
615
case GSSNTLM_NAME_SERVER :
616
+ safefree (name -> data .server .spn );
563
617
safefree (name -> data .server .name );
564
618
break ;
565
619
}
@@ -635,7 +689,7 @@ uint32_t gssntlm_display_name(uint32_t *minor_status,
635
689
}
636
690
break ;
637
691
case GSSNTLM_NAME_SERVER :
638
- out -> value = strdup (in -> data .server .name );
692
+ out -> value = strdup (in -> data .server .spn );
639
693
if (!out -> value ) {
640
694
set_GSSERR (ENOMEM );
641
695
goto done ;
0 commit comments