Browse code

secsipid: redesign to use per-process API functions

- needed to initialize the multi-threaded libsecsipid library per child
process
- per-process API functions to be offered by secsipid_proc module

Daniel-Constantin Mierla authored on 15/02/2021 07:34:05
Showing 6 changed files
... ...
@@ -6,27 +6,6 @@
6 6
 include ../../Makefile.defs
7 7
 auto_gen=
8 8
 NAME=secsipid.so
9
-
10
-ifeq ($(CROSS_COMPILE),)
11
-	BUILDER = $(shell which pkg-config)
12
-ifneq ($(BUILDER),)
13
-	PKGLIBSECSIPID = $(shell $(BUILDER) --exists secsipid-1 > /dev/null 2>&1 ; echo $$? )
14
-ifneq ($(PKGLIBSECSIPID),0)
15
-	BUILDER =
16
-endif
17
-endif
18
-endif
19
-
20
-ifeq ($(BUILDER),)
21
-	DEFS+= -I.
22
-	LIBS = -L. -lsecsipid
23
-else
24
-	DEFS+= $(shell pkg-config --cflags secsipid-1)
25
-	LIBS = $(shell pkg-config --libs secsipid-1)
26
-endif
27
-
28
-ifeq ($(OS), darwin)
29
-LIBS+= -framework CoreFoundation -framework Security -lpthread
30
-endif
9
+LIBS=
31 10
 
32 11
 include ../../Makefile.modules
... ...
@@ -24,17 +24,23 @@
24 24
 	<para>
25 25
 		It exports the functions to check and generate SIP Identity header.
26 26
 	</para>
27
+	<para>
28
+		Note that this module needs "secsipid_proc.so" module to be installed,
29
+		but without loading the "secsipid_proc.so" via "loadmodule". This module
30
+		loads "secsipid_proc.so" in child init callback in order to initialize
31
+		the "libsecsipid" per child process.
32
+	</para>
27 33
 	</section>
28 34
 	<section>
29 35
 	<title>Dependencies</title>
30 36
 	<section>
31 37
 		<title>&kamailio; Modules</title>
32 38
 		<para>
33
-		The following modules must be loaded before this module:
39
+		The following modules must be installed (but not loaded) to use this module:
34 40
 			<itemizedlist>
35 41
 			<listitem>
36 42
 			<para>
37
-				<emphasis>No dependencies on other &kamailio; modules</emphasis>.
43
+				<emphasis>secsipid_proc</emphasis>.
38 44
 			</para>
39 45
 			</listitem>
40 46
 			</itemizedlist>
... ...
@@ -48,7 +54,7 @@
48 54
 			<itemizedlist>
49 55
 			<listitem>
50 56
 			<para>
51
-				<emphasis>libsecsipid</emphasis> - https://github.com/asipto/secsipidx/.
57
+				<emphasis>none</emphasis>.
52 58
 			</para>
53 59
 			</listitem>
54 60
 			</itemizedlist>
... ...
@@ -137,7 +143,25 @@ modparam("secsipid", "cache_expire", 7200)
137 143
 </programlisting>
138 144
 		</example>
139 145
 	</section>
140
-
146
+	<section id="secsipid.p.modproc">
147
+		<title><varname>modproc</varname> (str)</title>
148
+		<para>
149
+		The name of or the path to the required per-process API module.
150
+		</para>
151
+		<para>
152
+		<emphasis>
153
+			Default value is "secsipid_proc.so".
154
+		</emphasis>
155
+		</para>
156
+		<example>
157
+		<title>Set <varname>modproc</varname> parameter</title>
158
+		<programlisting format="linespecific">
159
+...
160
+modparam("secsipid", "modproc", "secsipid_proc2.so")
161
+...
162
+</programlisting>
163
+		</example>
164
+	</section>
141 165
 	</section>
142 166
 
143 167
 	<section>
144 168
deleted file mode 100644
... ...
@@ -1,148 +0,0 @@
1
-/* Code generated by cmd/cgo; DO NOT EDIT. */
2
-
3
-/* package command-line-arguments */
4
-
5
-
6
-#line 1 "cgo-builtin-export-prolog"
7
-
8
-#include <stddef.h> /* for ptrdiff_t below */
9
-
10
-#ifndef GO_CGO_EXPORT_PROLOGUE_H
11
-#define GO_CGO_EXPORT_PROLOGUE_H
12
-
13
-#ifndef GO_CGO_GOSTRING_TYPEDEF
14
-typedef struct { const char *p; ptrdiff_t n; } _GoString_;
15
-#endif
16
-
17
-#endif
18
-
19
-/* Start of preamble from import "C" comments.  */
20
-
21
-
22
-
23
-
24
-/* End of preamble from import "C" comments.  */
25
-
26
-
27
-/* Start of boilerplate cgo prologue.  */
28
-#line 1 "cgo-gcc-export-header-prolog"
29
-
30
-#ifndef GO_CGO_PROLOGUE_H
31
-#define GO_CGO_PROLOGUE_H
32
-
33
-typedef signed char GoInt8;
34
-typedef unsigned char GoUint8;
35
-typedef short GoInt16;
36
-typedef unsigned short GoUint16;
37
-typedef int GoInt32;
38
-typedef unsigned int GoUint32;
39
-typedef long long GoInt64;
40
-typedef unsigned long long GoUint64;
41
-typedef GoInt64 GoInt;
42
-typedef GoUint64 GoUint;
43
-typedef __SIZE_TYPE__ GoUintptr;
44
-typedef float GoFloat32;
45
-typedef double GoFloat64;
46
-typedef float _Complex GoComplex64;
47
-typedef double _Complex GoComplex128;
48
-
49
-/*
50
-  static assertion to make sure the file is being used on architecture
51
-  at least with matching size of GoInt.
52
-*/
53
-typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
54
-
55
-#ifndef GO_CGO_GOSTRING_TYPEDEF
56
-typedef _GoString_ GoString;
57
-#endif
58
-typedef void *GoMap;
59
-typedef void *GoChan;
60
-typedef struct { void *t; void *v; } GoInterface;
61
-typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
62
-
63
-#endif
64
-
65
-/* End of boilerplate cgo prologue.  */
66
-
67
-#ifdef __cplusplus
68
-extern "C" {
69
-#endif
70
-
71
-
72
-// SecSIPIDSignJSONHP --
73
-// * sign the JSON header and payload with provided private key
74
-// * headerJSON -  header part in JSON forman (0-terminated string)
75
-// * payloadJSON -  payload part in JSON forman (0-terminated string)
76
-// * prvkeyPath - path to private key to be used to generate the signature
77
-// * outPtr - to be set to the pointer containing the output (it is a
78
-//   0-terminated string); the `*outPtr` must be freed after use
79
-// * return: the length of `*outPtr`
80
-extern int SecSIPIDSignJSONHP(char* headerJSON, char* payloadJSON, char* prvkeyPath, char** outPtr);
81
-
82
-// SecSIPIDGetIdentity --
83
-// Generate the Identity header content using the input attributes
84
-// * origTN - calling number
85
-// * destTN - called number
86
-// * attestVal - attestation level
87
-// * origID - unique ID for tracking purposes, if empty string a UUID is generated
88
-// * x5uVal - location of public certificate
89
-// * prvkeyPath - path to private key to be used to generate the signature
90
-// * outPtr - to be set to the pointer containing the output (it is a
91
-//   0-terminated string); the `*outPtr` must be freed after use
92
-// * return: the length of `*outPtr`
93
-extern int SecSIPIDGetIdentity(char* origTN, char* destTN, char* attestVal, char* origID, char* x5uVal, char* prvkeyPath, char** outPtr);
94
-
95
-// SecSIPIDCheck --
96
-// check the Identity header value
97
-// * identityVal - identity header value
98
-// * identityLen - length of identityVal, if is 0, identityVal is expected
99
-//   to be 0-terminated
100
-// * expireVal - number of seconds until the validity is considered expired
101
-// * pubkeyPath - file path or URL to public key
102
-// * timeoutVal - timeout in seconds to try to fetch the public key via HTTP
103
-// * return: 0 - if validity is ok; <0 - on error or validity is not ok
104
-extern int SecSIPIDCheck(char* identityVal, int identityLen, int expireVal, char* pubkeyPath, int timeoutVal);
105
-
106
-// SecSIPIDCheckFull --
107
-// check the Identity header value
108
-// * identityVal - identity header value with header parameters
109
-// * identityLen - length of identityVal, if it is 0, identityVal is expected
110
-//   to be 0-terminated
111
-// * expireVal - number of seconds until the validity is considered expired
112
-// * pubkeyPath - file path or URL to public key
113
-// * timeoutVal - timeout in seconds to try to fetch the public key via HTTP
114
-// * return: 0 - if validity is ok; <0 - on error or validity is not ok
115
-extern int SecSIPIDCheckFull(char* identityVal, int identityLen, int expireVal, char* pubkeyPath, int timeoutVal);
116
-
117
-// SecSIPIDCheckFullPubKey --
118
-// check the Identity header value
119
-// * identityVal - identity header value with header parameters
120
-// * identityLen - length of identityVal, if it is 0, identityVal is expected
121
-//   to be 0-terminated
122
-// * expireVal - number of seconds until the validity is considered expired
123
-// * pubkeyVal - the value of the public key
124
-// * pubkeyLen - the length of the public key, if it is 0, then the pubkeyVal
125
-//   is expected to be 0-terminated
126
-// * return: 0 - if validity is ok; <0 - on error or validity is not ok
127
-extern int SecSIPIDCheckFullPubKey(char* identityVal, int identityLen, int expireVal, char* pubkeyVal, int pubkeyLen);
128
-
129
-// SecSIPIDSetFileCacheOptions --
130
-// set the options for local file caching of public keys
131
-// * dirPath - path to local directory where to store the files
132
-// * expireVal - number of the seconds after which to invalidate the cached file
133
-// * return: 0
134
-extern int SecSIPIDSetFileCacheOptions(char* dirPath, int expireVal);
135
-
136
-// SecSIPIDGetURLContent --
137
-// get the content of an URL
138
-// * urlVal - the HTTP or HTTPS URL
139
-// * timeoutVal - timeout in seconds to try to get the content of the HTTP URL
140
-// * outPtr - to be set to the pointer containing the output (it is a
141
-//   0-terminated string); the `*outPtr` must be freed after use
142
-// * outLen: to be set to the length of `*outPtr`
143
-// * return: 0 - on success; -1 - on failure
144
-extern int SecSIPIDGetURLContent(char* urlVal, int timeoutVal, char** outPtr, int* outLen);
145
-
146
-#ifdef __cplusplus
147
-}
148
-#endif
149 0
deleted file mode 100644
... ...
@@ -1,16 +0,0 @@
1
-/* header file for secsipid library */
2
-
3
-#ifndef __SECSIPID_H__
4
-#define __SECSIPID_H__
5
-
6
-#include "libsecsipid.h"
7
-
8
-/**
9
- * SECSIPID_VERSION = 0xAABBCC00
10
- * - corresponds to version AA.BB.CC
11
- * - last two hexdigits are left for patch extensions
12
- * - example: 0x1010000 corresponds to version 1.1.0
13
- */
14
-#define SECSIPID_VERSION 0x1010000
15
-
16
-#endif
... ...
@@ -25,7 +25,6 @@
25 25
 #include <stdlib.h>
26 26
 #include <string.h>
27 27
 
28
-#include <secsipid.h>
29 28
 
30 29
 #include "../../core/sr_module.h"
31 30
 #include "../../core/dprint.h"
... ...
@@ -34,6 +33,8 @@
34 33
 #include "../../core/lvalue.h"
35 34
 #include "../../core/kemi.h"
36 35
 
36
+#include "secsipid_papi.h"
37
+
37 38
 MODULE_VERSION
38 39
 
39 40
 static int secsipid_expire = 300;
... ...
@@ -41,6 +42,7 @@ static int secsipid_timeout = 5;
41 42
 
42 43
 static int secsipid_cache_expire = 3600;
43 44
 static str secsipid_cache_dir = str_init("");
45
+static str secsipid_modproc = str_init("secsipid_proc.so");
44 46
 
45 47
 static int mod_init(void);
46 48
 static int child_init(int);
... ...
@@ -52,6 +54,7 @@ static int w_secsipid_add_identity(sip_msg_t *msg, char *porigtn, char *pdesttn,
52 54
 			char *pattest, char *porigid, char *px5u, char *pkeypath);
53 55
 static int w_secsipid_get_url(sip_msg_t *msg, char *purl, char *pout);
54 56
 
57
+secsipid_papi_t _secsipid_papi = {0};
55 58
 
56 59
 /* clang-format off */
57 60
 static cmd_export_t cmds[]={
... ...
@@ -71,6 +74,7 @@ static param_export_t params[]={
71 74
 	{"timeout",       PARAM_INT,   &secsipid_timeout},
72 75
 	{"cache_expire",  PARAM_INT,   &secsipid_cache_expire},
73 76
 	{"cache_dir",     PARAM_STR,   &secsipid_cache_dir},
77
+	{"modproc",       PARAM_STR,   &secsipid_modproc},
74 78
 	{0, 0, 0}
75 79
 };
76 80
 
... ...
@@ -102,7 +106,54 @@ static int mod_init(void)
102 106
  */
103 107
 static int child_init(int rank)
104 108
 {
109
+	void *handle = NULL;
110
+	char *errstr = NULL;
111
+	char *modpath = NULL;
112
+	secsipid_proc_bind_f bind_f = NULL;
113
+
114
+	if(rank==PROC_MAIN || rank==PROC_TCP_MAIN || rank==PROC_INIT) {
115
+		LM_DBG("skipping child init for rank: %d\n", rank);
116
+		return 0;
117
+	}
118
+
119
+	if(ksr_locate_module(secsipid_modproc.s, &modpath)<0) {
120
+		return -1;
121
+	}
122
+
123
+	LM_DBG("trying to load <%s>\n", modpath);
124
+
125
+#ifndef RTLD_NOW
126
+/* for openbsd */
127
+#define RTLD_NOW DL_LAZY
128
+#endif
129
+	handle = dlopen(modpath, RTLD_NOW); /* resolve all symbols now */
130
+	if (handle==0) {
131
+		LM_ERR("could not open module <%s>: %s\n", modpath, dlerror());
132
+		goto error;
133
+	}
134
+	/* launch register */
135
+	bind_f = (secsipid_proc_bind_f)dlsym(handle, "secsipid_proc_bind");
136
+	if (((errstr=(char*)dlerror())==NULL) && bind_f!=NULL) {
137
+		/* no error - call it */
138
+		if(bind_f(&_secsipid_papi)<0) {
139
+			LM_ERR("filed to bind the api of proc module: %s\n", modpath);
140
+			goto error;
141
+		}
142
+		LM_DBG("bound to proc module: <%s>\n", modpath);
143
+	} else {
144
+		LM_ERR("failure - func: %p - error: %s\n", bind_f, (errstr)?errstr:"none");
145
+		goto error;
146
+	}
147
+	if(secsipid_modproc.s != modpath) {
148
+		pkg_free(modpath);
149
+	}
105 150
 	return 0;
151
+
152
+error:
153
+	if(secsipid_modproc.s != modpath) {
154
+		pkg_free(modpath);
155
+	}
156
+	return -1;
106 157
 }
107 158
 
108 159
 /**
... ...
@@ -140,10 +191,11 @@ static int ki_secsipid_check_identity(sip_msg_t *msg, str *keypath)
140 191
 	ibody = hf->body;
141 192
 
142 193
 	if(secsipid_cache_dir.len > 0) {
143
-		SecSIPIDSetFileCacheOptions(secsipid_cache_dir.s, secsipid_cache_expire);
194
+		_secsipid_papi.SecSIPIDSetFileCacheOptions(secsipid_cache_dir.s,
195
+				secsipid_cache_expire);
144 196
 	}
145
-	ret = SecSIPIDCheckFull(ibody.s, ibody.len, secsipid_expire, keypath->s,
146
-			secsipid_timeout);
197
+	ret = _secsipid_papi.SecSIPIDCheckFull(ibody.s, ibody.len, secsipid_expire,
198
+			keypath->s, secsipid_timeout);
147 199
 
148 200
 	if(ret==0) {
149 201
 		LM_DBG("identity check: ok\n");
... ...
@@ -192,8 +244,8 @@ static int ki_secsipid_check_identity_pubkey(sip_msg_t *msg, str *keyval)
192 244
 
193 245
 	ibody = hf->body;
194 246
 
195
-	ret = SecSIPIDCheckFullPubKey(ibody.s, ibody.len, secsipid_expire, keyval->s,
196
-			keyval->len);
247
+	ret = _secsipid_papi.SecSIPIDCheckFullPubKey(ibody.s, ibody.len,
248
+			secsipid_expire, keyval->s, keyval->len);
197 249
 
198 250
 	if(ret==0) {
199 251
 		LM_DBG("identity check: ok\n");
... ...
@@ -230,8 +282,8 @@ static int ki_secsipid_add_identity(sip_msg_t *msg, str *origtn, str *desttn,
230 282
 	str hdr = STR_NULL;
231 283
 	sr_lump_t *anchor = NULL;
232 284
 
233
-	ibody.len = SecSIPIDGetIdentity(origtn->s, desttn->s, attest->s, origid->s,
234
-			x5u->s, keypath->s, &ibody.s);
285
+	ibody.len = _secsipid_papi.SecSIPIDGetIdentity(origtn->s, desttn->s,
286
+			attest->s, origid->s, x5u->s, keypath->s, &ibody.s);
235 287
 
236 288
 	if(ibody.len<=0) {
237 289
 		goto error;
... ...
@@ -349,9 +401,11 @@ static sr_kemi_xval_t* ki_secsipid_get_url(sip_msg_t *msg, str *surl)
349 401
 	}
350 402
 
351 403
 	if(secsipid_cache_dir.len > 0) {
352
-		SecSIPIDSetFileCacheOptions(secsipid_cache_dir.s, secsipid_cache_expire);
404
+		_secsipid_papi.SecSIPIDSetFileCacheOptions(secsipid_cache_dir.s,
405
+				secsipid_cache_expire);
353 406
 	}
354
-	r = SecSIPIDGetURLContent(surl->s, secsipid_timeout, &_secsipid_get_url_val.s,
407
+	r = _secsipid_papi.SecSIPIDGetURLContent(surl->s, secsipid_timeout,
408
+			&_secsipid_get_url_val.s,
355 409
 			&_secsipid_get_url_val.len);
356 410
 	if(r!=0) {
357 411
 		sr_kemi_xval_null(&_sr_kemi_secsipid_xval, SR_KEMI_XVAL_NULL_EMPTY);
... ...
@@ -384,10 +438,11 @@ static int w_secsipid_get_url(sip_msg_t *msg, char *purl, char *povar)
384 438
 	}
385 439
 
386 440
 	if(secsipid_cache_dir.len > 0) {
387
-		SecSIPIDSetFileCacheOptions(secsipid_cache_dir.s, secsipid_cache_expire);
441
+		_secsipid_papi.SecSIPIDSetFileCacheOptions(secsipid_cache_dir.s,
442
+				secsipid_cache_expire);
388 443
 	}
389
-	r = SecSIPIDGetURLContent(surl.s, secsipid_timeout, &_secsipid_get_url_val.s,
390
-			&_secsipid_get_url_val.len);
444
+	r = _secsipid_papi.SecSIPIDGetURLContent(surl.s, secsipid_timeout,
445
+			&_secsipid_get_url_val.s, &_secsipid_get_url_val.len);
391 446
 	if(r!=0) {
392 447
 		return -1;
393 448
 	}
394 449
new file mode 100644
... ...
@@ -0,0 +1,52 @@
1
+/**
2
+ * Copyright (C) 2021 Daniel-Constantin Mierla (asipto.com)
3
+ *
4
+ * This file is part of Kamailio, a free SIP server.
5
+ *
6
+ * This file is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version
10
+ *
11
+ *
12
+ * This file is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
+ *
21
+ */
22
+
23
+
24
+#ifndef _SECSIPID_PAPI_H_
25
+#define _SECSIPID_PAPI_H_
26
+
27
+typedef struct secsipid_papi {
28
+	int (*SecSIPIDSignJSONHP)(char* headerJSON, char* payloadJSON,
29
+			char* prvkeyPath, char** outPtr);
30
+
31
+	int (*SecSIPIDGetIdentity)(char* origTN, char* destTN, char* attestVal,
32
+			char* origID, char* x5uVal, char* prvkeyPath, char** outPtr);
33
+
34
+	int (*SecSIPIDCheck)(char* identityVal, int identityLen, int expireVal,
35
+			char* pubkeyPath, int timeoutVal);
36
+
37
+	int (*SecSIPIDCheckFull)(char* identityVal, int identityLen, int expireVal,
38
+			char* pubkeyPath, int timeoutVal);
39
+
40
+	int (*SecSIPIDCheckFullPubKey)(char* identityVal, int identityLen,
41
+			int expireVal, char* pubkeyVal, int pubkeyLen);
42
+
43
+	int (*SecSIPIDSetFileCacheOptions)(char* dirPath, int expireVal);
44
+
45
+	int (*SecSIPIDGetURLContent)(char* urlVal, int timeoutVal, char** outPtr,
46
+			int* outLen);
47
+
48
+} secsipid_papi_t;
49
+
50
+typedef int (*secsipid_proc_bind_f)(secsipid_papi_t *papi);
51
+
52
+#endif