Asterisk - The Open Source Telephony Project  18.5.0
Functions
stir_shaken.c File Reference

Internal stir/shaken utilities. More...

#include "asterisk.h"
#include <openssl/evp.h>
#include <openssl/pem.h>
#include "asterisk/cli.h"
#include "asterisk/sorcery.h"
#include "stir_shaken.h"
#include "asterisk/res_stir_shaken.h"
Include dependency graph for stir_shaken.c:

Go to the source code of this file.

Functions

int stir_shaken_cli_show (void *obj, void *arg, int flags)
 Output configuration settings to the Asterisk CLI. More...
 
char * stir_shaken_get_serial_number_x509 (const char *path)
 Gets the serial number in hex form from the X509 certificate at path. More...
 
EVP_PKEY * stir_shaken_read_key (const char *path, int priv)
 Reads the public (or private) key from the specified path. More...
 
char * stir_shaken_tab_complete_name (const char *word, struct ao2_container *container)
 Tab completion for name matching with STIR/SHAKEN CLI commands. More...
 

Detailed Description

Internal stir/shaken utilities.

Definition in file stir_shaken.c.

Function Documentation

◆ stir_shaken_cli_show()

int stir_shaken_cli_show ( void *  obj,
void *  arg,
int  flags 
)

Output configuration settings to the Asterisk CLI.

Parameters
objA sorcery object containing configuration data
argAsterisk CLI argument object
flagsao2 container flags
Return values
0

Definition at line 35 of file stir_shaken.c.

References a, ast_cli(), AST_HANDLER_ONLY_STRING, ast_sorcery_object_get_id(), ast_sorcery_object_get_type(), ast_sorcery_objectset_create2(), ast_stir_shaken_sorcery(), ast_variable_list_sort(), ast_variables_destroy(), ast_cli_args::fd, ast_variable::name, ast_variable::next, options, and ast_variable::value.

Referenced by stir_shaken_certificate_show(), stir_shaken_certificate_show_all(), stir_shaken_general_show(), and stir_shaken_store_show().

36 {
37  struct ast_cli_args *a = arg;
38  struct ast_variable *options;
39  struct ast_variable *i;
40 
41  if (!obj) {
42  ast_cli(a->fd, "No stir/shaken configuration found\n");
43  return 0;
44  }
45 
48  if (!options) {
49  return 0;
50  }
51 
52  ast_cli(a->fd, "%s: %s\n", ast_sorcery_object_get_type(obj),
54 
55  for (i = options; i; i = i->next) {
56  ast_cli(a->fd, "\t%s: %s\n", i->name, i->value);
57  }
58 
59  ast_cli(a->fd, "\n");
60 
61  ast_variables_destroy(options);
62 
63  return 0;
64 }
struct ast_variable * next
struct ast_variable * ast_variable_list_sort(struct ast_variable *head)
Performs an in-place sort on the variable list by ascending name.
Definition: main/config.c:622
struct ast_variable * ast_sorcery_objectset_create2(const struct ast_sorcery *sorcery, const void *object, enum ast_sorcery_field_handler_flags flags)
Create an object set (KVP list) for an object.
Definition: sorcery.c:1511
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
Structure for variables, used for configurations and for channel variables.
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * ast_sorcery_object_get_type(const void *object)
Get the type of a sorcery object.
Definition: sorcery.c:2324
const int fd
Definition: cli.h:159
Use string handler only.
Definition: sorcery.h:137
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
struct ast_sorcery * ast_stir_shaken_sorcery(void)
Retrieve the stir/shaken sorcery context.
static struct test_options options
static struct test_val a

◆ stir_shaken_get_serial_number_x509()

char* stir_shaken_get_serial_number_x509 ( const char *  path)

Gets the serial number in hex form from the X509 certificate at path.

Note
The returned string will need to be freed by the caller
Parameters
pathThe full path of the X509 certificate
Return values
NULLon failure
serialnumber on success

Definition at line 140 of file stir_shaken.c.

References ast_log, ast_strdup, LOG_ERROR, and NULL.

Referenced by curl_public_key().

141 {
142  FILE *fp;
143  X509 *cert;
144  ASN1_INTEGER *serial;
145  BIGNUM *bignum;
146  char *serial_hex;
147  char *ret;
148 
149  fp = fopen(path, "r");
150  if (!fp) {
151  ast_log(LOG_ERROR, "Failed to open file %s\n", path);
152  return NULL;
153  }
154 
155  cert = PEM_read_X509(fp, NULL, NULL, NULL);
156  if (!cert) {
157  ast_log(LOG_ERROR, "Failed to read X.509 cert from file %s\n", path);
158  fclose(fp);
159  return NULL;
160  }
161 
162  serial = X509_get_serialNumber(cert);
163  if (!serial) {
164  ast_log(LOG_ERROR, "Failed to get serial number from certificate %s\n", path);
165  X509_free(cert);
166  fclose(fp);
167  return NULL;
168  }
169 
170  bignum = ASN1_INTEGER_to_BN(serial, NULL);
171  if (bignum == NULL) {
172  ast_log(LOG_ERROR, "Failed to convert serial to bignum for certificate %s\n", path);
173  X509_free(cert);
174  fclose(fp);
175  return NULL;
176  }
177 
178  /* This will return a string with memory allocated. After we get the string,
179  * we don't need the cert, file, or bignum references anymore, so free them
180  * and return the string, if BN_bn2hex was a success.
181  */
182  serial_hex = BN_bn2hex(bignum);
183  X509_free(cert);
184  fclose(fp);
185  BN_free(bignum);
186 
187  if (!serial_hex) {
188  ast_log(LOG_ERROR, "Failed to convert bignum to hex for certificate %s\n", path);
189  return NULL;
190  }
191 
192  ret = ast_strdup(serial_hex);
193  OPENSSL_free(serial_hex);
194  if (!ret) {
195  ast_log(LOG_ERROR, "Failed to dup serial from openssl for certificate %s\n", path);
196  return NULL;
197  }
198 
199  return ret;
200 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285

◆ stir_shaken_read_key()

EVP_PKEY* stir_shaken_read_key ( const char *  path,
int  priv 
)

Reads the public (or private) key from the specified path.

Parameters
pathThe path to the file containing the private key
privSpecify 0 for public, 1 for private
Return values
NULLon failure
Thepublic/private key on success

Definition at line 89 of file stir_shaken.c.

References ast_log, LOG_ERROR, and NULL.

Referenced by ast_stir_shaken_verify(), stir_shaken_certificate_apply(), and test_stir_shaken_create_cert().

90 {
91  EVP_PKEY *key = NULL;
92  FILE *fp;
93  X509 *cert = NULL;
94 
95  fp = fopen(path, "r");
96  if (!fp) {
97  ast_log(LOG_ERROR, "Failed to read %s key file '%s'\n", priv ? "private" : "public", path);
98  return NULL;
99  }
100 
101  /* If this is to get the private key, the file will be ECDSA or RSA, with the former eventually
102  * replacing the latter. For the public key, the file will be X.509.
103  */
104  if (priv) {
105  key = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
106  } else {
107  cert = PEM_read_X509(fp, NULL, NULL, NULL);
108  if (!cert) {
109  ast_log(LOG_ERROR, "Failed to read X.509 cert from file '%s'\n", path);
110  fclose(fp);
111  return NULL;
112  }
113  key = X509_get_pubkey(cert);
114  /* It's fine to free the cert after we get the key because they are 2
115  * independent objects; you don't need a X509 object to be in memory
116  * in order to have an EVP_PKEY, and it doesn't rely on it being there.
117  */
118  X509_free(cert);
119  }
120 
121  if (!key) {
122  ast_log(LOG_ERROR, "Failed to read %s key from file '%s'\n", priv ? "private" : "public", path);
123  fclose(fp);
124  return NULL;
125  }
126 
127  if (EVP_PKEY_id(key) != EVP_PKEY_EC && EVP_PKEY_id(key) != EVP_PKEY_RSA) {
128  ast_log(LOG_ERROR, "%s key from '%s' must be of type EVP_PKEY_EC or EVP_PKEY_RSA\n",
129  priv ? "Private" : "Public", path);
130  fclose(fp);
131  EVP_PKEY_free(key);
132  return NULL;
133  }
134 
135  fclose(fp);
136 
137  return key;
138 }
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285

◆ stir_shaken_tab_complete_name()

char* stir_shaken_tab_complete_name ( const char *  word,
struct ao2_container container 
)

Tab completion for name matching with STIR/SHAKEN CLI commands.

Parameters
wordThe word to tab complete on
containerThe sorcery container to iterate through
Return values
Thetab completion options

Definition at line 66 of file stir_shaken.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli_completion_add(), ast_sorcery_object_get_id(), ast_strdup, and NULL.

Referenced by stir_shaken_certificate_show(), and stir_shaken_store_show().

67 {
68  void *obj;
69  struct ao2_iterator it;
70  int wordlen = strlen(word);
71  int ret;
72 
73  it = ao2_iterator_init(container, 0);
74  while ((obj = ao2_iterator_next(&it))) {
75  if (!strncasecmp(word, ast_sorcery_object_get_id(obj), wordlen)) {
77  if (ret) {
78  ao2_ref(obj, -1);
79  break;
80  }
81  }
82  ao2_ref(obj, -1);
83  }
85 
86  return NULL;
87 }
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2312
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2726
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
short word