summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorschwarze <>2018-03-01 19:20:09 +0000
committerschwarze <>2018-03-01 19:20:09 +0000
commit893043b7af14ee6af7eee004b42062b2c049e457 (patch)
treeca4f1bb2e50da9e74f1977f635e2ea2411ef9dfe /src
parentb83b4fa941f2349dbda1f5f85d6e5ee3c31b6eb5 (diff)
downloadopenbsd-893043b7af14ee6af7eee004b42062b2c049e457.tar.gz
openbsd-893043b7af14ee6af7eee004b42062b2c049e457.tar.bz2
openbsd-893043b7af14ee6af7eee004b42062b2c049e457.zip
Two new manual pages OPENSSL_sk_new(3) and STACK_OF(3), written from
scratch, tweaks and OK jsing@ and jmc@.
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/man/Makefile4
-rw-r--r--src/lib/libcrypto/man/OPENSSL_sk_new.3563
-rw-r--r--src/lib/libcrypto/man/STACK_OF.3183
3 files changed, 749 insertions, 1 deletions
diff --git a/src/lib/libcrypto/man/Makefile b/src/lib/libcrypto/man/Makefile
index 248bd33c8d..58b3cc2847 100644
--- a/src/lib/libcrypto/man/Makefile
+++ b/src/lib/libcrypto/man/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.135 2018/02/25 20:26:51 schwarze Exp $ 1# $OpenBSD: Makefile,v 1.136 2018/03/01 19:20:09 schwarze Exp $
2 2
3.include <bsd.own.mk> 3.include <bsd.own.mk>
4 4
@@ -157,6 +157,7 @@ MAN= \
157 OPENSSL_config.3 \ 157 OPENSSL_config.3 \
158 OPENSSL_load_builtin_modules.3 \ 158 OPENSSL_load_builtin_modules.3 \
159 OPENSSL_malloc.3 \ 159 OPENSSL_malloc.3 \
160 OPENSSL_sk_new.3 \
160 OpenSSL_add_all_algorithms.3 \ 161 OpenSSL_add_all_algorithms.3 \
161 PEM_bytes_read_bio.3 \ 162 PEM_bytes_read_bio.3 \
162 PEM_read.3 \ 163 PEM_read.3 \
@@ -202,6 +203,7 @@ MAN= \
202 SHA1.3 \ 203 SHA1.3 \
203 SMIME_read_PKCS7.3 \ 204 SMIME_read_PKCS7.3 \
204 SMIME_write_PKCS7.3 \ 205 SMIME_write_PKCS7.3 \
206 STACK_OF.3 \
205 SXNET_new.3 \ 207 SXNET_new.3 \
206 TS_REQ_new.3 \ 208 TS_REQ_new.3 \
207 UI_UTIL_read_pw.3 \ 209 UI_UTIL_read_pw.3 \
diff --git a/src/lib/libcrypto/man/OPENSSL_sk_new.3 b/src/lib/libcrypto/man/OPENSSL_sk_new.3
new file mode 100644
index 0000000000..5fe87b8fca
--- /dev/null
+++ b/src/lib/libcrypto/man/OPENSSL_sk_new.3
@@ -0,0 +1,563 @@
1.\" $OpenBSD: OPENSSL_sk_new.3,v 1.1 2018/03/01 19:20:09 schwarze Exp $
2.\"
3.\" Copyright (c) 2018 Ingo Schwarze <schwarze@openbsd.org>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd $Mdocdate: March 1 2018 $
18.Dt OPENSSL_SK_NEW 3
19.Os
20.Sh NAME
21.Nm sk_new_null ,
22.Nm sk_new ,
23.Nm sk_set_cmp_func ,
24.Nm sk_dup ,
25.Nm sk_free ,
26.Nm sk_pop_free ,
27.Nm sk_num ,
28.Nm sk_value ,
29.Nm sk_find ,
30.Nm sk_find_ex ,
31.Nm sk_sort ,
32.Nm sk_is_sorted ,
33.Nm sk_push ,
34.Nm sk_unshift ,
35.Nm sk_insert ,
36.Nm sk_set ,
37.Nm sk_pop ,
38.Nm sk_shift ,
39.Nm sk_delete ,
40.Nm sk_delete_ptr ,
41.Nm sk_zero
42.Nd variable-sized arrays of void pointers, called OpenSSL stacks
43.Sh SYNOPSIS
44.In openssl/stack.h
45.Ft _STACK *
46.Fn sk_new_null void
47.Ft _STACK *
48.Fo sk_new
49.Fa "int (*compfunc)(const void *, const void *)"
50.Fc
51.Ft old_function_pointer
52.Fo sk_set_cmp_func
53.Fa "_STACK *stack"
54.Fa "int (*compfunc)(const void *, const void *)"
55.Fc
56.Ft _STACK *
57.Fo sk_dup
58.Fa "_STACK *stack"
59.Fc
60.Ft void
61.Fo sk_free
62.Fa "_STACK *stack"
63.Fc
64.Ft void
65.Fo sk_pop_free
66.Fa "_STACK *stack"
67.Fa "void (*freefunc)(void *)"
68.Fc
69.Ft int
70.Fo sk_num
71.Fa "const _STACK *stack"
72.Fc
73.Ft void *
74.Fo sk_value
75.Fa "const _STACK *stack"
76.Fa "int index"
77.Fc
78.Ft int
79.Fo sk_find
80.Fa "_STACK *stack"
81.Fa "void *wanted"
82.Fc
83.Ft int
84.Fo sk_find_ex
85.Fa "_STACK *stack"
86.Fa "void *wanted"
87.Fc
88.Ft void
89.Fo sk_sort
90.Fa "_STACK *stack"
91.Fc
92.Ft int
93.Fo sk_is_sorted
94.Fa "const _STACK *stack"
95.Fc
96.Ft int
97.Fo sk_push
98.Fa "_STACK *stack"
99.Fa "void *new_item"
100.Fc
101.Ft int
102.Fo sk_unshift
103.Fa "_STACK *stack"
104.Fa "void *new_item"
105.Fc
106.Ft int
107.Fo sk_insert
108.Fa "_STACK *stack"
109.Fa "void *new_item"
110.Fa "int index"
111.Fc
112.Ft void *
113.Fo sk_set
114.Fa "_STACK *stack"
115.Fa "int index"
116.Fa "void *new_item"
117.Fc
118.Ft void *
119.Fo sk_pop
120.Fa "_STACK *stack"
121.Fc
122.Ft void *
123.Fo sk_shift
124.Fa "_STACK *stack"
125.Fc
126.Ft void *
127.Fo sk_delete
128.Fa "_STACK *stack"
129.Fa "int index"
130.Fc
131.Ft void *
132.Fo sk_delete_ptr
133.Fa "_STACK *stack"
134.Fa "void *wanted"
135.Fc
136.Ft void
137.Fo sk_zero
138.Fa "_STACK *stack"
139.Fc
140.Sh DESCRIPTION
141OpenSSL introduced an idiosyncratic concept of variable sized arrays
142of pointers and somewhat misleadingly called such an array a
143.Dq stack .
144Intrinsically, and as documented in this manual page, OpenSSL stacks
145are not type safe but only handle
146.Vt void *
147function arguments and return values.
148.Pp
149OpenSSL also provides a fragile, unusually complicated system of
150macro-generates wrappers that offers superficial type safety at the
151expense of extensive obfuscation, implemented using large amounts
152of autogenerated code involving exceedingly ugly, nested
153.Xr cpp 1
154macros; see the
155.Xr STACK_OF 3
156manual page for details.
157.Pp
158The fundamental data type is the
159.Vt _STACK
160structure.
161It stores a variable number of void pointers
162and remembers the number of pointers currently stored.
163It can optionally hold a pointer to a comparison function.
164As long as no comparison function is installed, the order of pointers
165is meaningful; as soon as a comparison function is installed, it
166becomes ill-defined.
167.Pp
168.Fn sk_new_null
169allocates and initializes a new, empty stack.
170.Fn sk_new
171is identical except that it also installs
172.Fa compfunc
173as the comparison function for the new stack object.
174.Fn sk_set_cmp_func
175installs
176.Fa compfunc
177for the existing
178.Fa stack .
179The
180.Fa compfunc
181is allowed to be
182.Dv NULL ,
183but the
184.Fa stack
185is not.
186.Pp
187.Fn sk_dup
188creates a shallow copy of the given
189.Fa stack ,
190which must not be a
191.Dv NULL
192pointer.
193It neither copies the objects pointed to from the stack nor
194increases their reference counts, but merely copies the pointers.
195Extreme care must be taken in order to avoid freeing the memory twice,
196for example by calling
197.Fn sk_free
198on one copy and only calling
199.Fn sk_pop_free
200on the other.
201.Pp
202.Fn sk_free
203frees the given
204.Fa stack .
205It does not free any of the pointers stored on the stack.
206Unless these pointers are merely copies of pointers owner by
207other objects, they must be freed before calling
208.Fn sk_free ,
209in order to avoid leaking memory.
210If
211.Fa stack
212is a
213.Dv NULL
214pointer, no action occurs.
215.Pp
216.Fn sk_pop_free
217is severely misnamed.
218It does not at all do what one would expect from a function called
219.Dq pop .
220Instead, it does the same as
221.Fn sk_free ,
222except that it also calls the function
223.Fa freefunc
224on each of the pointers contained in the
225.Fa stack .
226If the calls to
227.Fa freefunc
228are intended to free the memory in use by the objects on the stack,
229ensure that no other pointers to the same objects remain elsewhere.
230.Pp
231.Fn sk_find
232searches the
233.Fa stack
234for the
235.Fa wanted
236pointer.
237If the
238.Fa stack
239contains more than one copy of the
240.Fa wanted
241pointer, only the first match is found.
242If a comparison function is installed for the stack, the stack is
243first sorted with
244.Fn sk_sort ,
245and instead of comparing pointers, two pointers are considered to match
246if the comparison function returns 0.
247.Pp
248.Fn sk_find_ex
249is identical to
250.Fn sk_find
251except that if the
252.Fa stack
253is not empty but no match is found,
254the index of some pointer considered closest to
255.Fa wanted
256is returned.
257.Pp
258.Fn sk_sort
259sorts the
260.Fa stack
261using
262.Xr qsort 3
263and the installed comparison function.
264If
265.Fa stack
266is a
267.Dv NULL
268pointer or already considered sorted, no action occurs.
269This function can only be called if a comparison function is installed.
270.Pp
271.Fn sk_is_sorted
272reports whether the
273.Fa stack
274is considered sorted.
275Calling
276.Fn sk_new_null
277or
278.Fn sk_new ,
279successfuly calling
280.Fn sk_push ,
281.Fn sk_unshift ,
282or
283.Fn sk_insert ,
284or changing the comparison function sets the state to unsorted.
285If a comparison function is installed, calling
286.Fn sk_sort ,
287.Fn sk_find ,
288or
289.Fn sk_find_ex
290sets the state to sorted.
291.Pp
292.Fn sk_push
293pushes
294.Fa new_item
295onto the end of the
296.Fa stack ,
297increasing the number of pointers by 1.
298If
299.Fa stack
300is a
301.Dv NULL
302pointer, no action occurs.
303.Pp
304.Fn sk_unshift
305inserts
306.Fa new_item
307at the beginning of the
308.Fa stack ,
309such that it gets the index 0.
310The number of pointers increases by 1.
311If
312.Fa stack
313is a
314.Dv NULL
315pointer, no action occurs.
316.Pp
317.Fn sk_insert
318inserts the
319.Fa new_item
320into the
321.Fa stack
322such that it gets the given
323.Fa index .
324If
325.Fa index
326is less than 0 or greater than or equal to
327.Fn sk_num stack ,
328the effect is the same as for
329.Fn sk_push .
330If
331.Fa stack
332is a
333.Dv NULL
334pointer, no action occurs.
335.Pp
336.Fn sk_set
337replaces the pointer with the given
338.Fa index
339on the
340.Fa stack
341with the
342.Fa new_item .
343The old pointer is not freed,
344which may leak memory if no copy of it exists elsewhere.
345If
346.Fa stack
347is a
348.Dv NULL
349pointer or if
350.Fa index
351is less than 0 or greater than or equal to
352.Fn sk_num stack ,
353no action occurs.
354.Pp
355.Fn sk_pop
356and
357.Fn sk_shift
358remove the pointer with the highest or lowest index from the
359.Fa stack ,
360respectively, reducing the number of pointers by 1.
361If
362.Fa stack
363is a
364.Dv NULL
365pointer or if it is empty, no action occurs.
366.Pp
367.Fn sk_delete
368removes the pointer with the given
369.Fa index
370from the
371.Fa stack ,
372reducing the number of pointers by 1.
373If
374.Fa stack
375is a
376.Dv NULL
377pointer or the
378.Fa index
379is less than 0 or greater than or equal to
380.Fn sk_num stack ,
381no action occurs.
382.Pp
383.Fn sk_delete_ptr
384removes the
385.Fa wanted
386pointer from the
387.Fa stack ,
388reducing the number of pointers by 1 if it is found.
389It never uses a comparison function
390but only compares pointers themselves.
391The
392.Fa stack
393pointer must not be
394.Dv NULL .
395.Pp
396.Fn sk_zero
397removes all pointers from the
398.Fa stack .
399It does not free any of the pointers.
400Unless these pointers are merely copies of pointers owner by other
401objects, they must be freed before calling sk_zero(), in order to
402avoid leaking memory.
403If
404.Fa stack
405is a
406.Dv NULL
407pointer, no action occurs.
408.Sh RETURN VALUES
409.Fn sk_new_null ,
410.Fn sk_new ,
411and
412.Fn sk_dup
413return a pointer to the newly allocated stack object or
414.Dv NULL
415if insufficient memory is available.
416.Pp
417.Fn sk_set_cmp_func
418returns a pointer to the comparison function
419that was previously installed for the
420.Fa stack
421or
422.Dv NULL
423if none was installed.
424.Pp
425.Fn sk_num
426returns the number of pointers currently stored on the
427.Fa stack ,
428or \-1 if
429.Fa stack
430is a
431.Dv NULL
432pointer.
433.Pp
434.Fn sk_value
435returns the pointer with the given
436.Fa index
437from the
438.Fa stack ,
439or
440.Dv NULL
441if
442.Fa stack
443is a
444.Dv NULL
445pointer or if the
446.Fa index
447is less than 0 or greater than or equal to
448.Fn sk_num stack .
449.Pp
450.Fn sk_find
451returns the lowest index considered to match or \-1 if
452.Fa stack
453is a
454.Dv NULL
455pointer or if no match is found.
456.Pp
457.Fn sk_find_ex
458returns some index or \-1 if
459.Fa stack
460is a
461.Dv NULL
462pointer or empty.
463.Pp
464.Fn sk_is_sorted
465returns 1 if the
466.Fa stack
467is considered sorted or if it is a
468.Dv NULL
469pointer, or 0 otherwise.
470.Pp
471.Fn sk_push ,
472.Fn sk_unshift ,
473and
474.Fn sk_insert
475return the new number of pointers on the
476.Fa stack
477or 0 if
478.Fa stack
479is a
480.Dv NULL
481pointer or if memory allocation fails.
482.Pp
483.Fn sk_set
484returns
485.Fa new_item
486or
487.Dv NULL
488if
489.Fa stack
490is a
491.Dv NULL
492pointer or if the
493.Fa index
494is less than 0 or greater than or equal to
495.Fn sk_num stack .
496.Pp
497.Fn sk_pop
498and
499.Fn sk_shift
500return the deleted pointer or
501.Dv NULL
502if
503.Fa stack
504is a
505.Dv NULL
506pointer or if it is empty.
507.Pp
508.Fn sk_delete
509returns the deleted pointer or
510.Dv NULL
511if
512.Fa stack
513is a
514.Dv NULL
515pointer or if the
516.Fa index
517is less than 0 or greater than or equal to
518.Fn sk_num stack .
519.Pp
520.Fn sk_delete_ptr
521returns
522.Fa wanted
523or
524.Dv NULL
525if it is not found.
526.Sh BUGS
527.Fn sk_set
528does not set the state of the
529.Fa stack
530to unsorted.
531This can cause wrong results from subsequent
532.Fn sk_find
533and
534.Fn sk_find_ex .
535.Pp
536Even if a comparison function is installed, empty stacks and
537stacks containing a single pointer are sometimes considered
538sorted and sometimes considered unsorted.
539.Pp
540If a comparison function is installed, the concept of
541.Dq first match
542in
543.Fn sk_find
544and
545.Fn sk_find_ex
546is ill-defined because
547.Xr qsort 3
548is not a stable sorting function.
549It is probably best to only assume that they return an arbitrary match.
550.Pp
551The concept of
552.Dq closest
553for
554.Fn sk_find_ex
555is even less clearly defined.
556The match may sometimes be smaller and sometimes larger than
557.Fa wanted ,
558even if both smaller and larger pointers exist in the
559.Fa stack .
560Besides, it is again ill-defined
561which of several pointers that compare equal is selected.
562It is probably best to not assume anything about the selection
563for cases where there is no match.
diff --git a/src/lib/libcrypto/man/STACK_OF.3 b/src/lib/libcrypto/man/STACK_OF.3
new file mode 100644
index 0000000000..206d7faec3
--- /dev/null
+++ b/src/lib/libcrypto/man/STACK_OF.3
@@ -0,0 +1,183 @@
1.\" $OpenBSD: STACK_OF.3,v 1.1 2018/03/01 19:20:09 schwarze Exp $
2.\"
3.\" Copyright (c) 2018 Ingo Schwarze <schwarze@openbsd.org>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd $Mdocdate: March 1 2018 $
18.Dt STACK_OF 3
19.Os
20.Sh NAME
21.Nm STACK_OF
22.Nd variable-sized arrays of pointers, called OpenSSL stacks
23.Sh SYNOPSIS
24.In openssl/safestack.h
25.Fn STACK_OF type
26.Sh DESCRIPTION
27The
28.In openssl/safestack.h
29header provides a fragile, unusually complicated system of
30macro-generated wrappers around the functions described in the
31.Xr OPENSSL_sk_new 3
32manual page.
33It is intended to implement superficially type-safe variable-sized
34arrays of pointers, somewhat misleadingly called
35.Dq stacks
36by OpenSSL.
37Due to the excessive number of API functions, it is impossible to
38properly document this system.
39In particular, calling
40.Xr man 1
41for any of the functions operating on stacks cannot yield any result.
42.Pp
43Unfortunately, application programs can hardly avoid using the concept
44because several important OpenSSL APIs rely on it; see the
45.Sx SEE ALSO
46section for examples.
47Even though both pages are more complicated than any manual page
48ought to be, using the concept safely requires a complete understanding
49of all the details in both this manual page and in
50.Xr OPENSSL_sk_new 3 .
51.Pp
52The
53.Fn STACK_OF
54macro takes a
55.Fa type
56name as its argument, typically the name of a type
57that has been defined as an alias for a specific
58.Vt struct
59type using a
60.Sy typedef
61declaration.
62It expands to an incomplete
63.Vt struct
64type which is intended to represent a
65.Dq stack
66of objects of the given
67.Fa type .
68That type does not actually exist, so it is not possible to define,
69for example, an automatic variable
70.Ql STACK_OF(X509) my_certificates ;
71it is only possible to define pointers to stacks, for example
72.Ql STACK_OF(X509) *my_certificates .
73The only way such pointers can ever be used is by wrapper functions
74casting them to the type
75.Vt _STACK *
76described in
77.Xr OPENSSL_sk_new 3 .
78.Pp
79For a considerable number of types, OpenSSL provides one wrapper
80function for each function described in
81.Xr OPENSSL_sk_new 3 .
82The names of these wrapper functions are usually constructed by
83inserting the name of the type and an underscore after the
84.Sq sk_
85prefix of the function name.
86Usually, where the real functions take
87.Vt void *
88arguments, the wrappers take pointers to the
89.Fa type
90in questions, and where the real functions take
91.Vt _STACK *
92arguments, the wrappers take pointers to
93.Fn STACK_OF type .
94The same applies to return values.
95Various exceptions to all this exist, but the above applies to
96all the types listed below.
97.Pp
98Using the above may make sense for the following types because
99public API functions exist that take stacks of these types as
100arguments or return them:
101.Vt ACCESS_DESCRIPTION ,
102.Vt ASN1_INTEGER ,
103.Vt ASN1_OBJECT ,
104.Vt ASN1_TYPE ,
105.Vt ASN1_UTF8STRING ,
106.Vt CONF_VALUE ,
107.Vt DIST_POINT ,
108.Vt GENERAL_NAME ,
109.Vt GENERAL_SUBTREE ,
110.Vt PKCS12_SAFEBAG ,
111.Vt PKCS7 ,
112.Vt PKCS7_RECIP_INFO ,
113.Vt PKCS7_SIGNER_INFO ,
114.Vt POLICY_MAPPING ,
115.Vt POLICYINFO ,
116.Vt POLICYQUALINFO ,
117.Vt X509 ,
118.Vt X509_ALGOR ,
119.Vt X509_ATTRIBUTE ,
120.Vt X509_CRL ,
121.Vt X509_EXTENSION ,
122.Vt X509_INFO ,
123.Vt X509_OBJECT ,
124.Vt X509_POLICY_NODE ,
125.Vt X509_PURPOSE ,
126.Vt X509_REVOKED .
127.Pp
128Even though the OpenSSL headers declare wrapper functions for many
129more types and even though the OpenSSL documentation says that users
130can declare their own stack types, using
131.Fn STACK_OF
132with any type not listed here is strongly discouraged.
133For other types, there may be subtle, undocumented differences
134in syntax and semantics, and attempting to declare custom stack
135types is very error prone; using plain C arrays of pointers to
136the desired type is much simpler and less dangerous.
137.Sh EXAMPLES
138The following program creates a certificate object, puts two
139pointers to it on a stack, and uses
140.Xr X509_free 3
141to clean up properly:
142.Bd -literal
143#include <err.h>
144#include <stdio.h>
145#include <openssl/x509.h>
146
147int
148main(void)
149{
150 STACK_OF(X509) *stack;
151 X509 *x;
152
153 if ((stack = sk_X509_new_null()) == NULL)
154 err(1, NULL);
155 if ((x = X509_new()) == NULL)
156 err(1, NULL);
157 if (sk_X509_push(stack, x) == 0)
158 err(1, NULL);
159 if (X509_up_ref(x) == 0)
160 errx(1, "X509_up_ref failed");
161 if (sk_X509_push(stack, x) == 0)
162 err(1, NULL);
163 printf("%d pointers: %p, %p\en", sk_X509_num(stack),
164 sk_X509_value(stack, 0), sk_X509_value(stack, 1));
165 sk_X509_pop_free(stack, X509_free);
166
167 return 0;
168}
169.Ed
170.Pp
171The output looks similar to:
172.Pp
173.Dl 2 pointers: 0x4693ff24c00, 0x4693ff24c00
174.Sh SEE ALSO
175.Xr OCSP_request_sign 3 ,
176.Xr PKCS12_parse 3 ,
177.Xr PKCS7_encrypt 3 ,
178.Xr SSL_CTX_set_client_CA_list 3 ,
179.Xr SSL_get_ciphers 3 ,
180.Xr SSL_get_peer_cert_chain 3 ,
181.Xr SSL_load_client_CA_file 3 ,
182.Xr X509_CRL_get_REVOKED 3 ,
183.Xr X509_STORE_CTX_get0_chain 3