1.\" $OpenBSD: STACK_OF.3,v 1.5 2021/10/24 13:10:46 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: October 24 2021 $ 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 ASN1_INTEGER , 102.Vt ASN1_OBJECT , 103.Vt ASN1_UTF8STRING , 104.Vt CMS_RecipientInfo , 105.Vt CMS_SignerInfo , 106.Vt CONF_VALUE , 107.Vt GENERAL_NAMES , 108.Vt GENERAL_SUBTREE , 109.Vt OPENSSL_STRING Pq which is just Vt char * , 110.Vt PKCS12_SAFEBAG , 111.Vt PKCS7 , 112.Vt PKCS7_RECIP_INFO , 113.Vt PKCS7_SIGNER_INFO , 114.Vt POLICYQUALINFO , 115.Vt SRTP_PROTECTION_PROFILE , 116.Vt SSL_CIPHER , 117.Vt SSL_COMP , 118.Vt X509 , 119.Vt X509_ALGOR , 120.Vt X509_ATTRIBUTE , 121.Vt X509_CRL , 122.Vt X509_EXTENSION , 123.Vt X509_INFO , 124.Vt X509_NAME , 125.Vt X509_OBJECT , 126.Vt X509_POLICY_NODE , 127.Vt X509_REVOKED . 128.Pp 129Additionally, some public API functions use the following types 130which are declared with 131.Sy typedef : 132.Bl -column STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS 133.It Vt STACK_OF(ACCESS_DESCRIPTION) Ta Vt AUTHORITY_INFO_ACCESS 134.It Vt STACK_OF(ASN1_OBJECT) Ta Vt EXTENDED_KEY_USAGE 135.It Vt STACK_OF(ASN1_TYPE) Ta Vt ASN1_SEQUENCE_ANY 136.It Vt STACK_OF(DIST_POINT) Ta Vt CRL_DIST_POINTS 137.It Vt STACK_OF(GENERAL_NAME) Ta Vt GENERAL_NAMES 138.It Vt STACK_OF(IPAddressFamily) Ta Vt IPAddrBlocks 139.It Vt STACK_OF(POLICY_MAPPING) Ta Vt POLICY_MAPPINGS 140.It Vt STACK_OF(POLICYINFO) Ta Vt CERTIFICATEPOLICIES 141.It Vt STACK_OF(X509_ALGOR) Ta Vt X509_ALGORS 142.It Vt STACK_OF(X509_EXTENSION) Ta Vt X509_EXTENSIONS 143.El 144.Pp 145Even though the OpenSSL headers declare wrapper functions for many 146more types and even though the OpenSSL documentation says that users 147can declare their own stack types, using 148.Fn STACK_OF 149with any type not listed here is strongly discouraged. 150For other types, there may be subtle, undocumented differences 151in syntax and semantics, and attempting to declare custom stack 152types is very error prone; using plain C arrays of pointers to 153the desired type is much simpler and less dangerous. 154.Sh EXAMPLES 155The following program creates a certificate object, puts two 156pointers to it on a stack, and uses 157.Xr X509_free 3 158to clean up properly: 159.Bd -literal 160#include <err.h> 161#include <stdio.h> 162#include <openssl/x509.h> 163 164int 165main(void) 166{ 167 STACK_OF(X509) *stack; 168 X509 *x; 169 170 if ((stack = sk_X509_new_null()) == NULL) 171 err(1, NULL); 172 if ((x = X509_new()) == NULL) 173 err(1, NULL); 174 if (sk_X509_push(stack, x) == 0) 175 err(1, NULL); 176 if (X509_up_ref(x) == 0) 177 errx(1, "X509_up_ref failed"); 178 if (sk_X509_push(stack, x) == 0) 179 err(1, NULL); 180 printf("%d pointers: %p, %p\en", sk_X509_num(stack), 181 sk_X509_value(stack, 0), sk_X509_value(stack, 1)); 182 sk_X509_pop_free(stack, X509_free); 183 184 return 0; 185} 186.Ed 187.Pp 188The output looks similar to: 189.Pp 190.Dl 2 pointers: 0x4693ff24c00, 0x4693ff24c00 191.Sh SEE ALSO 192.Xr crypto 3 , 193.Xr OCSP_request_sign 3 , 194.Xr OPENSSL_sk_new 3 , 195.Xr PKCS12_parse 3 , 196.Xr PKCS7_encrypt 3 , 197.Xr SSL_CTX_set_client_CA_list 3 , 198.Xr SSL_get_ciphers 3 , 199.Xr SSL_get_peer_cert_chain 3 , 200.Xr SSL_load_client_CA_file 3 , 201.Xr X509_CRL_get_REVOKED 3 , 202.Xr X509_STORE_CTX_get0_chain 3 203.Sh HISTORY 204The 205.Fn STACK_OF 206macro first appeared in OpenSSL 0.9.3 and has been available since 207.Ox 2.6 . 208