Branch data Line data Source code
1 : : /* name.c --- Implementation of GSS-API Name Manipulation functions.
2 : : * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Simon Josefsson
3 : : *
4 : : * This file is part of the Generic Security Service (GSS).
5 : : *
6 : : * GSS is free software; you can redistribute it and/or modify it
7 : : * under the terms of the GNU General Public License as published by
8 : : * the Free Software Foundation; either version 3 of the License, or
9 : : * (at your option) any later version.
10 : : *
11 : : * GSS is distributed in the hope that it will be useful, but WITHOUT
12 : : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 : : * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 : : * License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with GSS; if not, see http://www.gnu.org/licenses or write to
18 : : * the Free Software Foundation, Inc., 51 Franklin Street, Fifth
19 : : * Floor, Boston, MA 02110-1301, USA.
20 : : *
21 : : */
22 : :
23 : : #include "internal.h"
24 : :
25 : : /* _gss_find_mech */
26 : : #include "meta.h"
27 : :
28 : : /**
29 : : * gss_import_name:
30 : : * @minor_status: (Integer, modify) Mechanism specific status code.
31 : : * @input_name_buffer: (buffer, octet-string, read) Buffer containing
32 : : * contiguous string name to convert.
33 : : * @input_name_type: (Object ID, read, optional) Object ID specifying
34 : : * type of printable name. Applications may specify either
35 : : * GSS_C_NO_OID to use a mechanism-specific default printable
36 : : * syntax, or an OID recognized by the GSS-API implementation to
37 : : * name a specific namespace.
38 : : * @output_name: (gss_name_t, modify) Returned name in internal form.
39 : : * Storage associated with this name must be freed by the
40 : : * application after use with a call to gss_release_name().
41 : : *
42 : : * Convert a contiguous string name to internal form. In general, the
43 : : * internal name returned (via the @output_name parameter) will not
44 : : * be an MN; the exception to this is if the @input_name_type
45 : : * indicates that the contiguous string provided via the
46 : : * @input_name_buffer parameter is of type GSS_C_NT_EXPORT_NAME, in
47 : : * which case the returned internal name will be an MN for the
48 : : * mechanism that exported the name.
49 : : *
50 : : * Return value:
51 : : *
52 : : * `GSS_S_COMPLETE`: Successful completion.
53 : : *
54 : : * `GSS_S_BAD_NAMETYPE`: The input_name_type was unrecognized.
55 : : *
56 : : * `GSS_S_BAD_NAME`: The input_name parameter could not be interpreted
57 : : * as a name of the specified type.
58 : : *
59 : : * `GSS_S_BAD_MECH`: The input name-type was GSS_C_NT_EXPORT_NAME, but
60 : : * the mechanism contained within the input-name is not supported.
61 : : **/
62 : : OM_uint32
63 : 2 : gss_import_name (OM_uint32 * minor_status,
64 : : const gss_buffer_t input_name_buffer,
65 : : const gss_OID input_name_type, gss_name_t * output_name)
66 : : {
67 [ - + ]: 2 : if (!output_name)
68 : : {
69 [ # # ]: 0 : if (minor_status)
70 : 0 : *minor_status = 0;
71 : 0 : return GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_WRITE;
72 : : }
73 : :
74 : 2 : *output_name = malloc (sizeof (**output_name));
75 [ - + ]: 2 : if (!*output_name)
76 : : {
77 [ # # ]: 0 : if (minor_status)
78 : 0 : *minor_status = ENOMEM;
79 : 0 : return GSS_S_FAILURE;
80 : : }
81 : 2 : (*output_name)->length = input_name_buffer->length;
82 : 2 : (*output_name)->value = malloc (input_name_buffer->length);
83 [ - + ]: 2 : if (!(*output_name)->value)
84 : : {
85 : 0 : free (*output_name);
86 [ # # ]: 0 : if (minor_status)
87 : 0 : *minor_status = ENOMEM;
88 : 0 : return GSS_S_FAILURE;
89 : : }
90 : 4 : memcpy ((*output_name)->value,
91 : 2 : input_name_buffer->value, input_name_buffer->length);
92 : :
93 : 2 : (*output_name)->type = input_name_type;
94 : :
95 [ + - ]: 2 : if (minor_status)
96 : 2 : *minor_status = 0;
97 : 2 : return GSS_S_COMPLETE;
98 : : }
99 : :
100 : : /**
101 : : * gss_display_name:
102 : : * @minor_status: (Integer, modify) Mechanism specific status code.
103 : : * @input_name: (gss_name_t, read) Name to be displayed.
104 : : * @output_name_buffer: (buffer, character-string, modify) Buffer to
105 : : * receive textual name string. The application must free storage
106 : : * associated with this name after use with a call to
107 : : * gss_release_buffer().
108 : : * @output_name_type: (Object ID, modify, optional) The type of the
109 : : * returned name. The returned gss_OID will be a pointer into
110 : : * static storage, and should be treated as read-only by the caller
111 : : * (in particular, the application should not attempt to free
112 : : * it). Specify NULL if not required.
113 : : *
114 : : * Allows an application to obtain a textual representation of an
115 : : * opaque internal-form name for display purposes. The syntax of a
116 : : * printable name is defined by the GSS-API implementation.
117 : : *
118 : : * If input_name denotes an anonymous principal, the implementation
119 : : * should return the gss_OID value GSS_C_NT_ANONYMOUS as the
120 : : * output_name_type, and a textual name that is syntactically distinct
121 : : * from all valid supported printable names in output_name_buffer.
122 : : *
123 : : * If input_name was created by a call to gss_import_name, specifying
124 : : * GSS_C_NO_OID as the name-type, implementations that employ lazy
125 : : * conversion between name types may return GSS_C_NO_OID via the
126 : : * output_name_type parameter.
127 : : *
128 : : * Return value:
129 : : *
130 : : * `GSS_S_COMPLETE`: Successful completion.
131 : : *
132 : : * `GSS_S_BAD_NAME`: @input_name was ill-formed.
133 : : **/
134 : : OM_uint32
135 : 1 : gss_display_name (OM_uint32 * minor_status,
136 : : const gss_name_t input_name,
137 : : gss_buffer_t output_name_buffer, gss_OID * output_name_type)
138 : : {
139 [ - + ]: 1 : if (!input_name)
140 : : {
141 [ # # ]: 0 : if (minor_status)
142 : 0 : *minor_status = 0;
143 : 0 : return GSS_S_BAD_NAME;
144 : : }
145 : :
146 : 1 : output_name_buffer->length = input_name->length;
147 : 1 : output_name_buffer->value = malloc (input_name->length + 1);
148 [ - + ]: 1 : if (!output_name_buffer->value)
149 : : {
150 [ # # ]: 0 : if (minor_status)
151 : 0 : *minor_status = ENOMEM;
152 : 0 : return GSS_S_FAILURE;
153 : : }
154 [ + - ]: 1 : if (input_name->value)
155 : 1 : memcpy (output_name_buffer->value, input_name->value, input_name->length);
156 : :
157 [ - + ]: 1 : if (output_name_type)
158 : 0 : *output_name_type = input_name->type;
159 : :
160 [ + - ]: 1 : if (minor_status)
161 : 1 : *minor_status = 0;
162 : 1 : return GSS_S_COMPLETE;
163 : : }
164 : :
165 : : /**
166 : : * gss_compare_name:
167 : : * @minor_status: (Integer, modify) Mechanism specific status code.
168 : : * @name1: (gss_name_t, read) Internal-form name.
169 : : * @name2: (gss_name_t, read) Internal-form name.
170 : : * @name_equal: (boolean, modify) Non-zero - names refer to same
171 : : * entity. Zero - names refer to different entities (strictly, the
172 : : * names are not known to refer to the same identity).
173 : : *
174 : : * Allows an application to compare two internal-form names to
175 : : * determine whether they refer to the same entity.
176 : : *
177 : : * If either name presented to gss_compare_name denotes an anonymous
178 : : * principal, the routines should indicate that the two names do not
179 : : * refer to the same identity.
180 : : *
181 : : * Return value:
182 : : *
183 : : * `GSS_S_COMPLETE`: Successful completion.
184 : : *
185 : : * `GSS_S_BAD_NAMETYPE`: The two names were of incomparable types.
186 : : *
187 : : * `GSS_S_BAD_NAME`: One or both of name1 or name2 was ill-formed.
188 : : **/
189 : : OM_uint32
190 : 0 : gss_compare_name (OM_uint32 * minor_status,
191 : : const gss_name_t name1,
192 : : const gss_name_t name2, int *name_equal)
193 : : {
194 [ # # ]: 0 : if (minor_status)
195 : 0 : *minor_status = 0;
196 : :
197 [ # # ][ # # ]: 0 : if (!name1 || !name2)
198 : 0 : return GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ;
199 : :
200 [ # # ]: 0 : if (!gss_oid_equal (name1->type, name2->type))
201 : 0 : return GSS_S_BAD_NAMETYPE;
202 : :
203 [ # # ]: 0 : if (name_equal)
204 [ # # ][ # # ]: 0 : *name_equal = (name1->length == name2->length) &&
205 : 0 : memcmp (name1->value, name2->value, name1->length) == 0;
206 : :
207 : 0 : return GSS_S_COMPLETE;
208 : : }
209 : :
210 : : /**
211 : : * gss_release_name:
212 : : * @minor_status: (Integer, modify) Mechanism specific status code.
213 : : * @name: (gss_name_t, modify) The name to be deleted.
214 : : *
215 : : * Free GSSAPI-allocated storage associated with an internal-form
216 : : * name. The name is set to GSS_C_NO_NAME on successful completion of
217 : : * this call.
218 : : *
219 : : * Return value:
220 : : *
221 : : * `GSS_S_COMPLETE`: Successful completion.
222 : : *
223 : : * `GSS_S_BAD_NAME`: The name parameter did not contain a valid name.
224 : : **/
225 : : OM_uint32
226 : 6 : gss_release_name (OM_uint32 * minor_status, gss_name_t * name)
227 : : {
228 [ + + ]: 6 : if (minor_status)
229 : 2 : *minor_status = 0;
230 : :
231 [ - + ]: 6 : if (!name)
232 : 0 : return GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ;
233 : :
234 [ + - ]: 6 : if (*name != GSS_C_NO_NAME)
235 : : {
236 [ + - ]: 6 : if ((*name)->value)
237 : 6 : free ((*name)->value);
238 : :
239 : 6 : free (*name);
240 : 6 : *name = GSS_C_NO_NAME;
241 : : }
242 : :
243 : 6 : return GSS_S_COMPLETE;
244 : : }
245 : :
246 : : /**
247 : : * gss_inquire_names_for_mech:
248 : : * @minor_status: (Integer, modify) Mechanism specific status code.
249 : : * @mechanism: (gss_OID, read) The mechanism to be interrogated.
250 : : * @name_types: (gss_OID_set, modify) Set of name-types supported by
251 : : * the specified mechanism. The returned OID set must be freed by
252 : : * the application after use with a call to gss_release_oid_set().
253 : : *
254 : : * Returns the set of nametypes supported by the specified mechanism.
255 : : *
256 : : * Return value:
257 : : *
258 : : * `GSS_S_COMPLETE`: Successful completion.
259 : : **/
260 : : OM_uint32
261 : 2 : gss_inquire_names_for_mech (OM_uint32 * minor_status,
262 : : const gss_OID mechanism, gss_OID_set * name_types)
263 : : {
264 : : OM_uint32 maj_stat;
265 : : _gss_mech_api_t mech;
266 : : int i;
267 : :
268 : 2 : mech = _gss_find_mech (mechanism);
269 : :
270 : 2 : maj_stat = gss_create_empty_oid_set (minor_status, name_types);
271 [ - + ]: 2 : if (maj_stat != GSS_S_COMPLETE)
272 : 0 : return maj_stat;
273 : :
274 [ + + ]: 8 : for (i = 0; mech->name_types[i]; i++)
275 : : {
276 : 6 : maj_stat = gss_add_oid_set_member (minor_status, mech->name_types[i],
277 : : name_types);
278 [ - + ]: 6 : if (maj_stat != GSS_S_COMPLETE)
279 : : {
280 : 0 : gss_release_oid_set (minor_status, name_types);
281 : 0 : return maj_stat;
282 : : }
283 : : }
284 : :
285 [ + - ]: 2 : if (minor_status)
286 : 2 : *minor_status = 0;
287 : 2 : return GSS_S_COMPLETE;
288 : : }
289 : :
290 : : /* Add mechanism MECH to OID set MECH_TYPES if mechanism MECH support
291 : : the NAME_TYPE name type. */
292 : : static OM_uint32
293 : 1 : _gss_inquire_mechs_for_name3 (OM_uint32 * minor_status,
294 : : gss_OID mech,
295 : : gss_OID name_type, gss_OID_set * mech_types)
296 : : {
297 : : gss_OID_set oids;
298 : : int supported;
299 : : OM_uint32 maj_stat;
300 : :
301 : 1 : maj_stat = gss_inquire_names_for_mech (minor_status, mech, &oids);
302 [ - + ]: 1 : if (GSS_ERROR (maj_stat))
303 : 0 : return maj_stat;
304 : :
305 : 1 : maj_stat = gss_test_oid_set_member (minor_status, name_type,
306 : : oids, &supported);
307 : 1 : gss_release_oid_set (minor_status, &oids);
308 [ - + ]: 1 : if (GSS_ERROR (maj_stat))
309 : 0 : return maj_stat;
310 : :
311 [ + - ]: 1 : if (supported)
312 : : {
313 : 1 : maj_stat = gss_add_oid_set_member (minor_status, mech, mech_types);
314 [ - + ]: 1 : if (GSS_ERROR (maj_stat))
315 : 0 : return maj_stat;
316 : : }
317 : :
318 [ + - ]: 1 : if (minor_status)
319 : 1 : *minor_status = 0;
320 : 1 : return GSS_S_COMPLETE;
321 : : }
322 : :
323 : : /* Iterate over SUPPORTED_MECH_TYPES and invoke
324 : : gss_inquire_mechs_for_name3 on each type, thus adding all mechanism
325 : : OIDs, that support the NAME_TYPE name type, to OUT_MECH_TYPES. */
326 : : static OM_uint32
327 : 1 : _gss_inquire_mechs_for_name2 (OM_uint32 * minor_status,
328 : : gss_OID name_type,
329 : : gss_OID_set * out_mech_types,
330 : : gss_OID_set supported_mech_types)
331 : : {
332 : : OM_uint32 maj_stat;
333 : : size_t i;
334 : :
335 [ + + ]: 2 : for (i = 0; i < supported_mech_types->count; i++)
336 : : {
337 : 1 : maj_stat = _gss_inquire_mechs_for_name3
338 : 1 : (minor_status, &(supported_mech_types->elements)[i],
339 : : name_type, out_mech_types);
340 [ - + ]: 1 : if (GSS_ERROR (maj_stat))
341 : 0 : return maj_stat;
342 : : }
343 : :
344 [ + - ]: 1 : if (minor_status)
345 : 1 : *minor_status = 0;
346 : 1 : return GSS_S_COMPLETE;
347 : : }
348 : :
349 : : /* List all supported mechanisms, and invoke
350 : : gss_inquire_mechs_for_name2, thus adding all mechanism OIDs, that
351 : : support the NAME_TYPE name type, to OUT_MECH_TYPES. */
352 : : static OM_uint32
353 : 1 : _gss_inquire_mechs_for_name1 (OM_uint32 * minor_status,
354 : : gss_OID name_type, gss_OID_set * out_mech_types)
355 : : {
356 : : OM_uint32 maj_stat;
357 : : gss_OID_set supported_mech_types;
358 : :
359 : 1 : maj_stat = gss_indicate_mechs (minor_status, &supported_mech_types);
360 [ - + ]: 1 : if (GSS_ERROR (maj_stat))
361 : 0 : return maj_stat;
362 : :
363 : 1 : maj_stat = _gss_inquire_mechs_for_name2 (minor_status, name_type,
364 : : out_mech_types,
365 : : supported_mech_types);
366 : 1 : gss_release_oid_set (minor_status, &supported_mech_types);
367 [ - + ]: 1 : if (GSS_ERROR (maj_stat))
368 : 0 : return maj_stat;
369 : :
370 [ + - ]: 1 : if (minor_status)
371 : 1 : *minor_status = 0;
372 : 1 : return GSS_S_COMPLETE;
373 : : }
374 : :
375 : : /**
376 : : * gss_inquire_mechs_for_name:
377 : : * @minor_status: (Integer, modify) Mechanism specific status code.
378 : : * @input_name: (gss_name_t, read) The name to which the inquiry
379 : : * relates.
380 : : * @mech_types: (gss_OID_set, modify) Set of mechanisms that may
381 : : * support the specified name. The returned OID set must be freed
382 : : * by the caller after use with a call to gss_release_oid_set().
383 : : *
384 : : * Returns the set of mechanisms supported by the GSS-API
385 : : * implementation that may be able to process the specified name.
386 : : *
387 : : * Each mechanism returned will recognize at least one element within
388 : : * the name. It is permissible for this routine to be implemented
389 : : * within a mechanism-independent GSS-API layer, using the type
390 : : * information contained within the presented name, and based on
391 : : * registration information provided by individual mechanism
392 : : * implementations. This means that the returned mech_types set may
393 : : * indicate that a particular mechanism will understand the name when
394 : : * in fact it would refuse to accept the name as input to
395 : : * gss_canonicalize_name, gss_init_sec_context, gss_acquire_cred or
396 : : * gss_add_cred (due to some property of the specific name, as opposed
397 : : * to the name type). Thus this routine should be used only as a
398 : : * prefilter for a call to a subsequent mechanism-specific routine.
399 : : *
400 : : * Return value:
401 : : *
402 : : * `GSS_S_COMPLETE`: Successful completion.
403 : : *
404 : : * `GSS_S_BAD_NAME`: The input_name parameter was ill-formed.
405 : : *
406 : : * `GSS_S_BAD_NAMETYPE`: The input_name parameter contained an invalid
407 : : * or unsupported type of name.
408 : : **/
409 : : OM_uint32
410 : 1 : gss_inquire_mechs_for_name (OM_uint32 * minor_status,
411 : : const gss_name_t input_name,
412 : : gss_OID_set * mech_types)
413 : : {
414 : : OM_uint32 maj_stat;
415 : :
416 [ - + ]: 1 : if (input_name == GSS_C_NO_NAME)
417 : : {
418 [ # # ]: 0 : if (minor_status)
419 : 0 : *minor_status = 0;
420 : 0 : return GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ;
421 : : }
422 : :
423 : 1 : maj_stat = gss_create_empty_oid_set (minor_status, mech_types);
424 [ - + ]: 1 : if (GSS_ERROR (maj_stat))
425 : 0 : return maj_stat;
426 : :
427 : 1 : maj_stat = _gss_inquire_mechs_for_name1 (minor_status,
428 : : input_name->type, mech_types);
429 [ - + ]: 1 : if (GSS_ERROR (maj_stat))
430 : : {
431 : 0 : gss_release_oid_set (minor_status, mech_types);
432 : 0 : return maj_stat;
433 : : }
434 : :
435 [ + - ]: 1 : if (minor_status)
436 : 1 : *minor_status = 0;
437 : 1 : return GSS_S_COMPLETE;
438 : : }
439 : :
440 : : /**
441 : : * gss_export_name:
442 : : * @minor_status: (Integer, modify) Mechanism specific status code.
443 : : * @input_name: (gss_name_t, read) The MN to be exported.
444 : : * @exported_name: (gss_buffer_t, octet-string, modify) The canonical
445 : : * contiguous string form of @input_name. Storage associated with
446 : : * this string must freed by the application after use with
447 : : * gss_release_buffer().
448 : : *
449 : : * To produce a canonical contiguous string representation of a
450 : : * mechanism name (MN), suitable for direct comparison (e.g. with
451 : : * memcmp) for use in authorization functions (e.g. matching entries
452 : : * in an access-control list). The @input_name parameter must specify
453 : : * a valid MN (i.e. an internal name generated by
454 : : * gss_accept_sec_context() or by gss_canonicalize_name()).
455 : : *
456 : : * Return value:
457 : : *
458 : : * `GSS_S_COMPLETE`: Successful completion.
459 : : *
460 : : * `GSS_S_NAME_NOT_MN`: The provided internal name was not a mechanism
461 : : * name.
462 : : *
463 : : * `GSS_S_BAD_NAME`: The provided internal name was ill-formed.
464 : : *
465 : : * `GSS_S_BAD_NAMETYPE`: The internal name was of a type not supported
466 : : * by the GSS-API implementation.
467 : : **/
468 : : OM_uint32
469 : 0 : gss_export_name (OM_uint32 * minor_status,
470 : : const gss_name_t input_name, gss_buffer_t exported_name)
471 : : {
472 : : OM_uint32 maj_stat;
473 : : gss_OID_set mechs;
474 : : _gss_mech_api_t mech;
475 : :
476 : 0 : maj_stat = gss_inquire_mechs_for_name (minor_status, input_name, &mechs);
477 [ # # ]: 0 : if (GSS_ERROR (maj_stat))
478 : 0 : return maj_stat;
479 : :
480 [ # # ]: 0 : if (mechs->count == 0)
481 : : {
482 [ # # ]: 0 : if (minor_status)
483 : 0 : *minor_status = 0;
484 : 0 : return GSS_S_BAD_NAMETYPE;
485 : : }
486 : :
487 : : /* We just select a random mechanism that support this name-type.
488 : : I'm not sure how we can be more predicatable, given the
489 : : definition of this function. */
490 : :
491 : 0 : mech = _gss_find_mech (mechs->elements);
492 [ # # ]: 0 : if (mech == NULL)
493 : : {
494 [ # # ]: 0 : if (minor_status)
495 : 0 : *minor_status = 0;
496 : 0 : return GSS_S_BAD_MECH;
497 : : }
498 : :
499 : 0 : return mech->export_name (minor_status, input_name, exported_name);
500 : : }
501 : :
502 : : /**
503 : : * gss_canonicalize_name:
504 : : * @minor_status: (Integer, modify) Mechanism specific status code.
505 : : * @input_name: (gss_name_t, read) The name for which a canonical form
506 : : * is desired.
507 : : * @mech_type: (Object ID, read) The authentication mechanism for
508 : : * which the canonical form of the name is desired. The desired
509 : : * mechanism must be specified explicitly; no default is provided.
510 : : * @output_name: (gss_name_t, modify) The resultant canonical name.
511 : : * Storage associated with this name must be freed by the
512 : : * application after use with a call to gss_release_name().
513 : : *
514 : : * Generate a canonical mechanism name (MN) from an arbitrary internal
515 : : * name. The mechanism name is the name that would be returned to a
516 : : * context acceptor on successful authentication of a context where
517 : : * the initiator used the input_name in a successful call to
518 : : * gss_acquire_cred, specifying an OID set containing @mech_type as
519 : : * its only member, followed by a call to gss_init_sec_context(),
520 : : * specifying @mech_type as the authentication mechanism.
521 : : *
522 : : * Return value:
523 : : *
524 : : * `GSS_S_COMPLETE`: Successful completion.
525 : : **/
526 : : OM_uint32
527 : 0 : gss_canonicalize_name (OM_uint32 * minor_status,
528 : : const gss_name_t input_name,
529 : : const gss_OID mech_type, gss_name_t * output_name)
530 : : {
531 : : _gss_mech_api_t mech;
532 : :
533 : 0 : mech = _gss_find_mech (mech_type);
534 [ # # ]: 0 : if (mech == NULL)
535 : : {
536 [ # # ]: 0 : if (minor_status)
537 : 0 : *minor_status = 0;
538 : 0 : return GSS_S_BAD_MECH;
539 : : }
540 : :
541 : 0 : return mech->canonicalize_name (minor_status, input_name,
542 : : mech_type, output_name);
543 : : }
544 : :
545 : : /**
546 : : * gss_duplicate_name:
547 : : * @minor_status: (Integer, modify) Mechanism specific status code.
548 : : * @src_name: (gss_name_t, read) Internal name to be duplicated.
549 : : * @dest_name: (gss_name_t, modify) The resultant copy of @src_name.
550 : : * Storage associated with this name must be freed by the application
551 : : * after use with a call to gss_release_name().
552 : : *
553 : : * Create an exact duplicate of the existing internal name @src_name.
554 : : * The new @dest_name will be independent of src_name (i.e. @src_name
555 : : * and @dest_name must both be released, and the release of one shall
556 : : * not affect the validity of the other).
557 : : *
558 : : * Return value:
559 : : *
560 : : * `GSS_S_COMPLETE`: Successful completion.
561 : : *
562 : : * `GSS_S_BAD_NAME`: The src_name parameter was ill-formed.
563 : : **/
564 : : OM_uint32
565 : 4 : gss_duplicate_name (OM_uint32 * minor_status,
566 : : const gss_name_t src_name, gss_name_t * dest_name)
567 : : {
568 [ - + ]: 4 : if (src_name == GSS_C_NO_NAME)
569 : : {
570 [ # # ]: 0 : if (minor_status)
571 : 0 : *minor_status = 0;
572 : 0 : return GSS_S_BAD_NAME;
573 : : }
574 : :
575 [ - + ]: 4 : if (!dest_name)
576 : : {
577 [ # # ]: 0 : if (minor_status)
578 : 0 : *minor_status = 0;
579 : 0 : return GSS_S_FAILURE | GSS_S_CALL_INACCESSIBLE_WRITE;
580 : : }
581 : :
582 : 4 : *dest_name = malloc (sizeof (**dest_name));
583 [ - + ]: 4 : if (!*dest_name)
584 : : {
585 [ # # ]: 0 : if (minor_status)
586 : 0 : *minor_status = ENOMEM;
587 : 0 : return GSS_S_FAILURE;
588 : : }
589 : 4 : (*dest_name)->type = src_name->type;
590 : 4 : (*dest_name)->length = src_name->length;
591 : 4 : (*dest_name)->value = malloc (src_name->length + 1);
592 [ - + ]: 4 : if (!(*dest_name)->value)
593 : : {
594 : 0 : free (*dest_name);
595 [ # # ]: 0 : if (minor_status)
596 : 0 : *minor_status = ENOMEM;
597 : 0 : return GSS_S_FAILURE;
598 : : }
599 : 4 : memcpy ((*dest_name)->value, src_name->value, src_name->length);
600 : 4 : (*dest_name)->value[src_name->length] = '\0';
601 : :
602 [ + - ]: 4 : if (minor_status)
603 : 4 : *minor_status = 0;
604 : 4 : return GSS_S_COMPLETE;
605 : : }
|