1 /*
2  * Copyright (c) 2007 iptelorg GmbH
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio 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  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 /*!
22  * \file
23  * \brief Kamailio auth-identity :: Crypt
24  * \ingroup auth-identity
25  * Module: \ref auth-identity
26  */
27 
28 
29 #define _GNU_SOURCE
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <openssl/pem.h>
34 #include <openssl/err.h>
35 #include <openssl/sha.h>
36 #include <openssl/x509.h>
37 #include <openssl/x509v3.h>
38 #include <openssl/crypto.h>
39 #include <openssl/x509_vfy.h>
40 
41 #include "../../core/mem/mem.h"
42 #include "../../core/parser/parse_uri.h"
43 
44 #include "auth_identity.h"
45 
46 
47 
retrieve_x509(X509 ** pcert,str * scert,int bacceptpem)48 int retrieve_x509(X509 **pcert, str *scert, int bacceptpem)
49 {
50 	BIO *bcer=NULL;
51 	char serr[160];
52 	int iRet=0;
53 
54 
55 	if (!(bcer=BIO_new(BIO_s_mem()))) {
56 		LOG(L_ERR, "AUTH_IDENTITY:retrieve_x509: Unable to create BIO\n");
57 
58 		return -1;
59 	}
60 
61 	do {
62 		if (BIO_write(bcer, scert->s, scert->len)!=scert->len) {
63 			LOG(L_ERR, "AUTH_IDENTITY:retrieve_x509: Unable to write BIO\n");
64 			iRet=-2;
65 			break;
66 		}
67 
68 		/* RFC 4474 only accepts certs in the DER form but it can not harm
69 		 * to be a little bit more flexible and accept PEM as well. */
70 		if (bacceptpem
71 		  	&& scert->len > BEGIN_PEM_CERT_LEN
72 			&& memmem(scert->s,
73 					  scert->len,
74 					  BEGIN_PEM_CERT,
75 					  BEGIN_PEM_CERT_LEN)) {
76 			if (!(*pcert = PEM_read_bio_X509(bcer, NULL, NULL, NULL))) {
77 				ERR_error_string_n(ERR_get_error(), serr, sizeof(serr));
78 				LOG(L_ERR, "AUTH_IDENTITY:retrieve_x509: PEM Certificate %s\n", serr);
79 				iRet=-4;
80 			}
81 		} else {
82 			if (!(*pcert = d2i_X509_bio(bcer, NULL))) {
83 				ERR_error_string_n(ERR_get_error(), serr, sizeof(serr));
84 				LOG(L_ERR, "AUTH_IDENTITY:retrieve_x509: DER Certificate %s\n", serr);
85 				iRet=-3;
86 			}
87 		}
88 	} while (0);
89 
90 	BIO_free(bcer);
91 
92 	return iRet;
93 }
94 
check_x509_subj(X509 * pcert,str * sdom)95 int check_x509_subj(X509 *pcert, str* sdom)
96 {
97 	STACK_OF(GENERAL_NAME) *altnames;
98 	int ialts, i1, ilen, altlen;
99 	const GENERAL_NAME *actname;
100 	char scname[AUTH_DOMAIN_LENGTH];
101 	char *altptr;
102 	struct sip_uri suri;
103 	int ret = 0;
104 
105 
106 	/* we're looking for subjectAltName for the first time */
107 	altnames = X509_get_ext_d2i(pcert, NID_subject_alt_name, NULL, NULL);
108 
109 	if (altnames) {
110 		ialts = sk_GENERAL_NAME_num(altnames);
111 
112 		for (i1=0; i1 < ialts; i1++) {
113 			actname = sk_GENERAL_NAME_value(altnames, i1);
114 
115 			if (actname->type == GEN_DNS || actname->type == GEN_URI) {
116 				/* we've found one */
117 #if OPENSSL_VERSION_NUMBER >= 0x010100000L
118 				altptr = (char *)ASN1_STRING_get0_data(actname->d.ia5);
119 #else
120 				altptr = (char *)ASN1_STRING_data(actname->d.ia5);
121 #endif
122 				if (actname->type == GEN_URI) {
123 					if (parse_uri(altptr, strlen(altptr), &suri) != 0) {
124 						continue;
125 					}
126 					if (!(suri.type == SIP_URI_T || suri.type == SIPS_URI_T)) {
127 						continue;
128 					}
129 					if (suri.user.len != 0 || suri.passwd.len != 0) {
130 						continue;
131 					}
132 					altptr = suri.host.s;
133 					altlen = suri.host.len;
134 				} else {
135 					altlen = strlen(altptr);
136 				}
137 				if (sdom->len != altlen
138 					|| strncasecmp(altptr, sdom->s, sdom->len)) {
139 					LOG(L_INFO, "AUTH_IDENTITY VERIFIER: subAltName of certificate doesn't match host name\n");
140 					ret = -1;
141 				} else {
142 					ret = 1;
143 					break;
144 				}
145 			}
146 		}
147 		GENERAL_NAMES_free(altnames);
148 	}
149 
150 	if (ret != 0) {
151 		return ret == 1 ? 0 : ret;
152  	}
153 
154 	/* certificate supplier host and certificate subject match check */
155 	ilen=X509_NAME_get_text_by_NID (X509_get_subject_name (pcert),
156 									NID_commonName,
157 									scname,
158 									sizeof (scname));
159 	if (sdom->len != ilen || strncasecmp(scname, sdom->s, sdom->len)) {
160 		LOG(L_INFO, "AUTH_IDENTITY VERIFIER: common name of certificate doesn't match host name\n");
161 		return -2;
162 	}
163 
164 	return 0;
165 }
166 
verify_x509(X509 * pcert,X509_STORE * pcacerts)167 int verify_x509(X509 *pcert, X509_STORE *pcacerts)
168 {
169 	X509_STORE_CTX *ca_ctx = NULL;
170 	char *strerr;
171 
172 	ca_ctx = X509_STORE_CTX_new();
173 	if(ca_ctx==NULL) {
174 		LM_ERR("cannot get a x509 context\n");
175 		return -1;
176 	}
177 
178 	if (X509_STORE_CTX_init(ca_ctx, pcacerts, pcert, NULL) != 1) {
179 		LOG(L_ERR, "AUTH_IDENTITY:verify_x509: Unable to init X509 store ctx\n");
180 		X509_STORE_CTX_free(ca_ctx);
181 		return -1;
182 	}
183 
184 	if (X509_verify_cert(ca_ctx) != 1) {
185 		strerr = (char *)X509_verify_cert_error_string(X509_STORE_CTX_get_error(ca_ctx));
186 		LOG(L_ERR, "AUTH_IDENTITY VERIFIER: Certificate verification error: %s\n", strerr);
187 		X509_STORE_CTX_cleanup(ca_ctx);
188 		X509_STORE_CTX_free(ca_ctx);
189 		return -2;
190 	}
191 	X509_STORE_CTX_cleanup(ca_ctx);
192 	X509_STORE_CTX_free(ca_ctx);
193 
194 	LOG(AUTH_DBG_LEVEL, "AUTH_IDENTITY VERIFIER: Certificate is valid\n");
195 
196 	return 0;
197 }
198 
rsa_sha1_enc(dynstr * sdigeststr,dynstr * senc,dynstr * sencb64,RSA * hmyprivkey)199 int rsa_sha1_enc (dynstr *sdigeststr,
200 				  dynstr *senc,
201 				  dynstr *sencb64,
202 				  RSA *hmyprivkey)
203 {
204 	unsigned char sstrcrypted[SHA_DIGEST_LENGTH];
205 	int ires;
206 	char serr[160];
207 
208 
209 	SHA1((unsigned char*)getstr_dynstr(sdigeststr).s,
210 		 getstr_dynstr(sdigeststr).len,
211 		 sstrcrypted);
212 
213 #ifdef NEW_RSA_PROC
214 	ires = senc->size;
215 	if (RSA_sign(NID_sha1,
216 			 	 sstrcrypted,
217 			 	 sizeof sstrcrypted,
218 				 (unsigned char*)getstr_dynstr(senc).s,
219 				 (unsigned int*)&ires,
220 			 	 hmyprivkey) != 1) {
221 		ERR_error_string_n(ERR_get_error(), serr, sizeof serr);
222 		LOG(L_ERR, "AUTH_IDENTITY:rsa_sha1_enc: '%s'\n", serr);
223 		return -2;
224 	}
225 #else
226 	ires=RSA_private_encrypt(sizeof sstrcrypted, sstrcrypted,
227 							 (unsigned char*)getstr_dynstr(senc).s, hmyprivkey,
228 							 RSA_PKCS1_PADDING );
229 	if (ires<0)
230 	{
231 		ERR_error_string_n(ERR_get_error(), serr, sizeof serr);
232 		LOG(L_ERR, "AUTH_IDENTITY:rsa_sha1_enc: '%s'\n", serr);
233 		return -1;
234 	}
235 #endif
236 
237 	base64encode(getstr_dynstr(senc).s, senc->size, getstr_dynstr(sencb64).s, &getstr_dynstr(sencb64).len );
238 
239 	return 0;
240 }
241 
rsa_sha1_dec(char * sencedsha,int iencedshalen,char * ssha,int sshasize,int * ishalen,X509 * pcertx509)242 int rsa_sha1_dec (char *sencedsha, int iencedshalen,
243 				  char *ssha, int sshasize, int *ishalen,
244 				  X509 *pcertx509)
245 {
246 	EVP_PKEY *pkey;
247 	RSA* hpubkey;
248 	unsigned long lerr;
249 	char serr[160];
250 
251 
252 	pkey=X509_get_pubkey(pcertx509);
253 	if (pkey == NULL) {
254 		lerr=ERR_get_error(); ERR_error_string_n(lerr, serr, sizeof(serr));
255 		LOG(L_ERR, "AUTH_IDENTITY:decrypt_identity: Pubkey %s\n", serr);
256 		return -1;
257 	}
258 
259 	X509_free(pcertx509);
260 
261 	hpubkey = EVP_PKEY_get1_RSA(pkey);
262 	EVP_PKEY_free(pkey);
263 	if (hpubkey == NULL) {
264 		LOG(L_ERR, "AUTH_IDENTITY:decrypt_identity: Error getting RSA key\n");
265 		return -2;
266 	}
267 
268 #ifdef NEW_RSA_PROC
269 	if (RSA_verify(NID_sha1,
270 		 			(unsigned char*)ssha, sshasize,
271 					(unsigned char*)sencedsha, iencedshalen,
272 					hpubkey) != 1) {
273 		LOG(L_INFO, "AUTH_IDENTITY VERIFIER: RSA verify returned: '%s'\n", ERR_error_string(ERR_get_error(), NULL));
274 		LOG(L_INFO, "AUTH_IDENTITY VERIFIER: RSA verify failed -> Invalid Identity Header\n");
275 		RSA_free(hpubkey);
276 		return -5;
277 	}
278 #else
279 	/* it is bigger than the output buffer */
280 	if (RSA_size(hpubkey) > sshasize) {
281 		LOG(L_ERR, "AUTH_IDENTITY:decrypt_identity: Unexpected Identity hash length (%d > %d)\n", RSA_size(hpubkey), sshasize);
282 		RSA_free(hpubkey);
283 		return -3;
284 	}
285 	*ishalen=RSA_public_decrypt(iencedshalen,
286 								(unsigned char*)sencedsha,
287 								(unsigned char*)ssha,
288 								hpubkey,
289 								RSA_PKCS1_PADDING);
290 	if (*ishalen<=0) {
291 		lerr=ERR_get_error(); ERR_error_string_n(lerr, serr, sizeof(serr));
292 		LOG(L_ERR, "AUTH_IDENTITY:decrypt_identity: RSA operation error %s\n", serr);
293 		RSA_free(hpubkey);
294 		return -4;
295 	}
296 #endif
297 
298 	RSA_free(hpubkey);
299 
300 	return 0;
301 }
302 
303 /* copypasted from ser/modules/rr/avp_cookie.c + this adds '=' sign! ) */
base64encode(char * src_buf,int src_len,char * tgt_buf,int * tgt_len)304 void base64encode(char* src_buf, int src_len, char* tgt_buf, int* tgt_len) {
305 	static char code64[64+1] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
306 	int pos;
307 	for (pos=0, *tgt_len=0; pos < src_len; pos+=3,*tgt_len+=4) {
308 		tgt_buf[*tgt_len+0] = code64[(unsigned char)src_buf[pos+0] >> 2];
309 		tgt_buf[*tgt_len+1] = code64[(((unsigned char)src_buf[pos+0] & 0x03) << 4) | ((pos+1 < src_len)?((unsigned char)src_buf[pos+1] >> 4):0)];
310 		if (pos+1 < src_len)
311 			tgt_buf[*tgt_len+2] = code64[(((unsigned char)src_buf[pos+1] & 0x0F) << 2) | ((pos+2 < src_len)?((unsigned char)src_buf[pos+2] >> 6):0)];
312 		else
313 			tgt_buf[*tgt_len+2] = '=';
314 		if (pos+2 < src_len)
315 			tgt_buf[*tgt_len+3] = code64[(unsigned char)src_buf[pos+2] & 0x3F];
316 		else
317 			tgt_buf[*tgt_len+3] = '=';
318 	}
319 }
320 
321 
322 /* copypasted from ser/modules/rr/avp_cookie.c */
base64decode(char * src_buf,int src_len,char * tgt_buf,int * tgt_len)323 void base64decode(char* src_buf, int src_len, char* tgt_buf, int* tgt_len) {
324 	int pos, i, n;
325 	unsigned char c[4];
326 	for (pos=0, i=0, *tgt_len=0; pos < src_len; pos++) {
327 		if (src_buf[pos] >= 'A' && src_buf[pos] <= 'Z')
328 			c[i] = src_buf[pos] - 65;   /* <65..90>  --> <0..25> */
329 		else if (src_buf[pos] >= 'a' && src_buf[pos] <= 'z')
330 			c[i] = src_buf[pos] - 71;   /* <97..122>  --> <26..51> */
331 		else if (src_buf[pos] >= '0' && src_buf[pos] <= '9')
332 			c[i] = src_buf[pos] + 4;    /* <48..56>  --> <52..61> */
333 		else if (src_buf[pos] == '+')
334 			c[i] = 62;
335 		else if (src_buf[pos] == '/')
336 			c[i] = 63;
337 		else  /* '=' */
338 			c[i] = 64;
339 		i++;
340 		if (pos == src_len-1) {
341 			while (i < 4) {
342 				c[i] = 64;
343 				i++;
344 			}
345 		}
346 		if (i==4) {
347 			if (c[0] == 64)
348 				n = 0;
349 			else if (c[2] == 64)
350 				n = 1;
351 			else if (c[3] == 64)
352 				n = 2;
353 			else
354 				n = 3;
355 			switch (n) {
356 				case 3:
357 					tgt_buf[*tgt_len+2] = (char) (((c[2] & 0x03) << 6) | c[3]);
358 					/* no break */
359 				case 2:
360 					tgt_buf[*tgt_len+1] = (char) (((c[1] & 0x0F) << 4) | (c[2] >> 2));
361 					/* no break */
362 				case 1:
363 					tgt_buf[*tgt_len+0] = (char) ((c[0] << 2) | (c[1] >> 4));
364 					break;
365 			}
366 			i=0;
367 			*tgt_len+= n;
368 		}
369 	}
370 }
371 
x509_get_validitytime(time_t * tout,ASN1_UTCTIME * tin)372 int x509_get_validitytime(time_t *tout, ASN1_UTCTIME *tin)
373 {
374 	char *sasn1;
375 	int i1;
376 	struct tm tmptm;
377 
378 
379 	memset(&tmptm, 0, sizeof(tmptm));
380 	i1=tin->length;
381 	sasn1=(char *)tin->data;
382 
383 	if (i1 < 10)
384 		return -1;
385 /*	if (sasn1[i1-1]!='Z')
386 		return -1;*/
387 	for (i1=0; i1<10; i1++)
388 		if((sasn1[i1] > '9') || (sasn1[i1] < '0'))
389 			return -2;
390 
391 	tmptm.tm_year=(sasn1[0]-'0')*10+(sasn1[1]-'0');
392 	if(tmptm.tm_year < 50)
393 		tmptm.tm_year+=100;
394 
395 	tmptm.tm_mon=(sasn1[2]-'0')*10+(sasn1[3]-'0')-1;
396 	if((tmptm.tm_mon > 11) || (tmptm.tm_mon < 0))
397 		return -3;
398 
399 	tmptm.tm_mday=(sasn1[4]-'0')*10+(sasn1[5]-'0');
400 	tmptm.tm_hour= (sasn1[6]-'0')*10+(sasn1[7]-'0');
401 	tmptm.tm_min=(sasn1[8]-'0')*10+(sasn1[9]-'0');
402 
403 	if ((sasn1[10] >= '0') && (sasn1[10] <= '9') &&
404 		   (sasn1[11] >= '0') && (sasn1[11] <= '9'))
405 		tmptm.tm_sec=(sasn1[10]-'0')*10+(sasn1[11]-'0');
406 
407 #ifdef HAVE_TIMEGM
408 	*tout=timegm(&tmptm);
409 #else
410 	*tout=_timegm(&tmptm);
411 #endif
412 
413 	return 0;
414 }
415 
x509_get_notbefore(time_t * tout,X509 * pcert)416 int x509_get_notbefore(time_t *tout, X509 *pcert)
417 {
418 	return (x509_get_validitytime(tout, X509_get_notBefore(pcert)));
419 }
420 
x509_get_notafter(time_t * tout,X509 * pcert)421 int x509_get_notafter(time_t *tout, X509 *pcert)
422 {
423 	return (x509_get_validitytime(tout, X509_get_notAfter(pcert)));
424 }
425