@@ -281,6 +281,128 @@ uint32_t gssntlm_import_name(uint32_t *minor_status,
281281 output_name );
282282}
283283
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+
284406int gssntlm_copy_name (struct gssntlm_name * src , struct gssntlm_name * dst )
285407{
286408 char * dom = NULL , * usr = NULL , * srv = NULL ;
@@ -320,6 +442,9 @@ int gssntlm_copy_name(struct gssntlm_name *src, struct gssntlm_name *dst)
320442 break ;
321443 }
322444
445+ ret = gssntlm_copy_attrs (src -> attrs , & dst -> attrs );
446+ if (ret ) goto done ;
447+
323448 ret = 0 ;
324449done :
325450 if (ret ) {
@@ -389,6 +514,7 @@ void gssntlm_int_release_name(struct gssntlm_name *name)
389514 safefree (name -> data .server .name );
390515 break ;
391516 }
517+ gssntlm_release_attrs (& name -> attrs );
392518 name -> type = GSSNTLM_NAME_NULL ;
393519}
394520
@@ -626,7 +752,107 @@ uint32_t gssntlm_inquire_name(uint32_t *minor_status,
626752 gss_OID * MN_mech ,
627753 gss_buffer_set_t * attrs )
628754{
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 );
630856}
631857
632858/* RFC5801 Extensions */
0 commit comments