@@ -281,6 +281,128 @@ uint32_t gssntlm_import_name(uint32_t *minor_status,
281
281
output_name );
282
282
}
283
283
284
+ size_t gssntlm_get_attrs_count (const struct gssntlm_name_attribute * attrs )
285
+ {
286
+ size_t c ;
287
+ for (c = 0 ; attrs && attrs [c ].attr_name != NULL ; c ++ ) ;
288
+ return c ;
289
+ }
290
+
291
+ int gssntlm_copy_attrs (const struct gssntlm_name_attribute * src ,
292
+ struct gssntlm_name_attribute * * dst )
293
+ {
294
+ struct gssntlm_name_attribute * copied_attrs ;
295
+ size_t attrs_count = gssntlm_get_attrs_count (src );
296
+
297
+ * dst = NULL ;
298
+ if (attrs_count == 0 ) {
299
+ return 0 ;
300
+ }
301
+
302
+ copied_attrs = calloc (attrs_count + 1 , /* +1 for terminator entry */
303
+ sizeof (struct gssntlm_name_attribute ));
304
+ if (copied_attrs == NULL ) {
305
+ return ENOMEM ;
306
+ }
307
+
308
+ for (size_t i = 0 ; i < attrs_count ; i ++ ) {
309
+ /* read-only persistent data ptr can be just copied */
310
+ copied_attrs [i ].attr_name = src [i ].attr_name ;
311
+ copied_attrs [i ].attr_value .length = src [i ].attr_value .length ;
312
+ copied_attrs [i ].attr_value .value = malloc (src [i ].attr_value .length );
313
+ if (copied_attrs [i ].attr_value .value == NULL ) {
314
+ gssntlm_release_attrs (& copied_attrs );
315
+ return ENOMEM ;
316
+ }
317
+ memcpy (copied_attrs [i ].attr_value .value , src [i ].attr_value .value ,
318
+ src [i ].attr_value .length );
319
+ }
320
+ /* terminator entry is filled with zeroes by calloc */
321
+
322
+ * dst = copied_attrs ;
323
+ return 0 ;
324
+ }
325
+
326
+ /* Low-level func with buffer ownership transfer
327
+ * attr_name - read-only static string, should not be released
328
+ * attr_value - ownership of that buffer is MOVED to dst
329
+ * (MUST NOT BE RELEASED from caller side) */
330
+ int gssntlm_append_attr (const char * attr_name , gss_buffer_t attr_value ,
331
+ struct gssntlm_name * dst )
332
+ {
333
+ size_t prev_attrs_count = gssntlm_get_attrs_count (dst -> attrs );
334
+ /* 1 for new attribute +1 for terminator entry */
335
+ size_t new_attrs_count = prev_attrs_count + 2 ;
336
+ struct gssntlm_name_attribute * attrs ;
337
+
338
+ if (!attr_name || !attr_value || !dst ) {
339
+ return ERR_NOARG ;
340
+ }
341
+
342
+ /* Increase buffer - if there was no any attributes before,
343
+ * realloc is identical to malloc */
344
+ attrs = realloc (dst -> attrs ,
345
+ new_attrs_count * sizeof (struct gssntlm_name_attribute ));
346
+ if (attrs == NULL ) {
347
+ return ENOMEM ;
348
+ }
349
+ dst -> attrs = attrs ;
350
+
351
+ attrs [prev_attrs_count ].attr_name = attr_name ;
352
+ attrs [prev_attrs_count ].attr_value .value = attr_value -> value ;
353
+ attrs [prev_attrs_count ].attr_value .length = attr_value -> length ;
354
+
355
+ /* Fill the last terminator entry with zeroes
356
+ beacuse realloc does not init added memory */
357
+ memset (& attrs [prev_attrs_count + 1 ], 0 , sizeof (struct gssntlm_name_attribute ));
358
+
359
+ return 0 ;
360
+ }
361
+
362
+ int gssntlm_append_attr_str (const char * attr_name , const char * attr_value ,
363
+ struct gssntlm_name * dst )
364
+ {
365
+ int ret ;
366
+ gss_buffer_desc buf ;
367
+ if (!attr_value ) {
368
+ return ERR_NOARG ;
369
+ }
370
+ buf .value = strdup (attr_value );
371
+ if (!buf .value ) {
372
+ return ENOMEM ;
373
+ }
374
+ buf .length = strlen (attr_value ) + 1 ; /* +1 for EOL */
375
+ ret = gssntlm_append_attr (attr_name , & buf , dst );
376
+ if (ret ) {
377
+ free (buf .value );
378
+ }
379
+ return ret ;
380
+ }
381
+
382
+ struct gssntlm_name_attribute * gssntlm_find_attr (
383
+ struct gssntlm_name_attribute * attrs ,
384
+ const char * attr_name ,
385
+ size_t attr_name_len )
386
+ {
387
+ for (size_t i = 0 ; attrs && (attrs [i ].attr_name != NULL ); i ++ ) {
388
+ /* We store attr_name as const static zero-terminated string, so
389
+ * it is always zero-terminated */
390
+ if (attr_name_len == strlen (attrs [i ].attr_name ) &&
391
+ strncasecmp (attrs [i ].attr_name , attr_name , attr_name_len ) == 0 ) {
392
+ return & attrs [i ];
393
+ }
394
+ }
395
+ return NULL ;
396
+ }
397
+
398
+ void gssntlm_release_attrs (struct gssntlm_name_attribute * * attrs )
399
+ {
400
+ for (size_t i = 0 ; * attrs && (* attrs )[i ].attr_name != NULL ; i ++ ) {
401
+ free ((* attrs )[i ].attr_value .value );
402
+ }
403
+ safefree (* attrs );
404
+ }
405
+
284
406
int gssntlm_copy_name (struct gssntlm_name * src , struct gssntlm_name * dst )
285
407
{
286
408
char * dom = NULL , * usr = NULL , * srv = NULL ;
@@ -320,6 +442,9 @@ int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst)
320
442
break ;
321
443
}
322
444
445
+ ret = gssntlm_copy_attrs (src -> attrs , & dst -> attrs );
446
+ if (ret ) goto done ;
447
+
323
448
ret = 0 ;
324
449
done :
325
450
if (ret ) {
@@ -389,6 +514,7 @@ void gssntlm_int_release_name(struct gssntlm_name *name)
389
514
safefree (name -> data .server .name );
390
515
break ;
391
516
}
517
+ gssntlm_release_attrs (& name -> attrs );
392
518
name -> type = GSSNTLM_NAME_NULL ;
393
519
}
394
520
@@ -626,7 +752,107 @@ uint32_t gssntlm_inquire_name(uint32_t *minor_status,
626
752
gss_OID * MN_mech ,
627
753
gss_buffer_set_t * attrs )
628
754
{
629
- return GSS_S_UNAVAILABLE ;
755
+ uint32_t retmin = 0 ;
756
+ uint32_t retmaj = 0 ;
757
+ uint32_t tmpmin ;
758
+ const struct gssntlm_name * in = (const struct gssntlm_name * )name ;
759
+
760
+ if (!attrs ) {
761
+ return GSSERRS (ERR_NOARG , GSS_S_CALL_INACCESSIBLE_WRITE );
762
+ }
763
+ * attrs = GSS_C_NO_BUFFER_SET ;
764
+
765
+ if (name == GSS_C_NO_NAME ) {
766
+ return GSSERRS (GSS_S_BAD_NAME , GSS_S_CALL_INACCESSIBLE_READ );
767
+ }
768
+
769
+ for (size_t i = 0 ; in -> attrs && in -> attrs [i ].attr_name != NULL ; i ++ ) {
770
+ struct gssntlm_name_attribute * attr = & in -> attrs [i ];
771
+ size_t attr_name_len = strlen (attr -> attr_name );
772
+ gss_buffer_desc buf ;
773
+ gss_buffer_t attr_value = & attr -> attr_value ;
774
+ /* +1 for '=' separator and +1 for EOL */
775
+ size_t full_string_len = attr_value -> length + attr_name_len + 2 ;
776
+ size_t offset = 0 ;
777
+ char * attr_string = malloc (full_string_len );
778
+ if (attr_string == NULL ) {
779
+ set_GSSERR (ENOMEM );
780
+ goto done ;
781
+ }
782
+
783
+ /* Construct 'attr_name=<attr_value>\0' string */
784
+ memcpy (attr_string , attr -> attr_name , attr_name_len );
785
+ offset += attr_name_len ;
786
+
787
+ attr_string [offset ++ ] = '=' ;
788
+
789
+ memcpy (attr_string + offset , attr_value -> value , attr_value -> length );
790
+ offset += attr_value -> length ;
791
+
792
+ attr_string [offset ] = 0 ;
793
+
794
+ /* now add a buffer to output set */
795
+ buf .length = full_string_len ;
796
+ buf .value = attr_string ;
797
+ retmaj = gss_add_buffer_set_member (& retmin , & buf , attrs );
798
+ free (attr_string );
799
+ if (retmaj != GSS_S_COMPLETE ) goto done ;
800
+ }
801
+
802
+ done :
803
+ if (retmaj ) {
804
+ (void )gss_release_buffer_set (& tmpmin , attrs );
805
+ }
806
+ return GSSERRS (retmin , retmaj );
807
+ }
808
+
809
+ /* RFC6680 - GSSAPI Naming Extensions */
810
+ uint32_t gssntlm_get_name_attribute (uint32_t * minor_status ,
811
+ gss_name_t name ,
812
+ gss_buffer_t attr ,
813
+ int * authenticated ,
814
+ int * complete ,
815
+ gss_buffer_t value ,
816
+ gss_buffer_t display_value ,
817
+ int * more )
818
+ {
819
+ uint32_t retmin ;
820
+ uint32_t retmaj ;
821
+ const struct gssntlm_name * in = (const struct gssntlm_name * )name ;
822
+ struct gssntlm_name_attribute * found_attr ;
823
+
824
+ if (name == GSS_C_NO_NAME ) {
825
+ return GSSERRS (GSS_S_BAD_NAME , GSS_S_CALL_INACCESSIBLE_READ );
826
+ }
827
+ if (attr == NULL ) {
828
+ return GSSERRS (ERR_NOARG , GSS_S_CALL_INACCESSIBLE_READ );
829
+ }
830
+
831
+ if (display_value ) {
832
+ display_value -> value = NULL ;
833
+ display_value -> length = 0 ;
834
+ }
835
+ if (more ) { * more = 0 ; }
836
+ if (authenticated ) { * authenticated = 0 ; }
837
+ if (complete ) { * complete = 0 ; }
838
+
839
+ found_attr = gssntlm_find_attr (in -> attrs , attr -> value , attr -> length );
840
+ if (!found_attr ) {
841
+ return GSSERRS (ENOENT , GSS_S_UNAVAILABLE );
842
+ }
843
+
844
+ if (authenticated ) { * authenticated = 1 ; }
845
+ if (complete ) { * complete = 1 ; }
846
+ if (value ) {
847
+ gss_buffer_t attr_value = & found_attr -> attr_value ;
848
+ value -> value = malloc (attr_value -> length );
849
+ if (!value -> value ) {
850
+ return GSSERRS (ENOMEM , GSS_S_FAILURE );
851
+ }
852
+ memcpy (value -> value , attr_value -> value , attr_value -> length );
853
+ value -> length = attr_value -> length ;
854
+ }
855
+ return GSSERRS (0 , GSS_S_COMPLETE );
630
856
}
631
857
632
858
/* RFC5801 Extensions */
0 commit comments