1 /*
2  * Copyright (C) 2011-2019 Free Software Foundation, Inc.
3  * Copyright (C) 2019 Red Hat, Inc.
4  *
5  * Author: Nikos Mavrogiannopoulos
6  *
7  * This file is part of GnuTLS.
8  *
9  * The GnuTLS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program.  If not, see <https://www.gnu.org/licenses/>
21  *
22  */
23 
24 #ifndef GNUTLS_NAME_VAL_ARRAY_H
25 #define GNUTLS_NAME_VAL_ARRAY_H
26 
27 #include "gnutls_int.h"
28 #include "errors.h"
29 
30 /* Functionality to allow an array of strings. Strings
31  * are allowed to be added to the list and matched against it.
32  */
33 
34 typedef struct name_val_array_st {
35 	char *name;
36 	unsigned name_size;
37 	char *val;
38 	struct name_val_array_st *next;
39 } *name_val_array_t;
40 
_name_val_array_init(name_val_array_t * head)41 inline static void _name_val_array_init(name_val_array_t * head)
42 {
43 	*head = NULL;
44 }
45 
_name_val_array_clear(name_val_array_t * head)46 inline static void _name_val_array_clear(name_val_array_t * head)
47 {
48 	name_val_array_t prev, array = *head;
49 
50 	while (array != NULL) {
51 		prev = array;
52 		array = prev->next;
53 		gnutls_free(prev);
54 	}
55 	*head = NULL;
56 }
57 
_name_val_array_value(name_val_array_t head,const char * name,unsigned name_size)58 inline static const char *_name_val_array_value(name_val_array_t head,
59 					        const char *name, unsigned name_size)
60 {
61 	name_val_array_t array = head;
62 
63 	while (array != NULL) {
64 		if (array->name_size == name_size &&
65 		    memcmp(array->name, name, name_size) == 0) {
66 			return array->val;
67 		}
68 		array = array->next;
69 	}
70 
71 	return NULL;
72 }
73 
append(name_val_array_t array,const char * name,unsigned name_len,const char * val,unsigned val_len)74 inline static void append(name_val_array_t array, const char *name,
75 			  unsigned name_len, const char *val,
76 			  unsigned val_len)
77 {
78 	array->name = ((char *) array) + sizeof(struct name_val_array_st);
79 	memcpy(array->name, name, name_len);
80 	array->name[name_len] = 0;
81 	array->name_size = name_len;
82 
83 	array->val = ((char *) array) + name_len + 1 + sizeof(struct name_val_array_st);
84 	if (val)
85 		memcpy(array->val, val, val_len);
86 	array->val[val_len] = 0;
87 
88 	array->next = NULL;
89 }
90 
_name_val_array_append(name_val_array_t * head,const char * name,const char * val)91 inline static int _name_val_array_append(name_val_array_t * head,
92 					 const char *name,
93 					 const char *val)
94 {
95 	name_val_array_t prev, array;
96 	unsigned name_len = strlen(name);
97 	unsigned val_len = (val==NULL)?0:strlen(val);
98 
99 	if (*head == NULL) {
100 		*head =
101 		    gnutls_malloc(val_len + name_len + 2 +
102 				  sizeof(struct name_val_array_st));
103 		if (*head == NULL)
104 			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
105 
106 		array = *head;
107 		append(array, name, name_len, val, val_len);
108 	} else {
109 		array = *head;
110 		prev = array;
111 
112 		while (array != NULL) {
113 			prev = array;
114 			array = prev->next;
115 		}
116 		prev->next =
117 		    gnutls_malloc(name_len + val_len + 2 +
118 				  sizeof(struct name_val_array_st));
119 		array = prev->next;
120 
121 		if (array == NULL)
122 			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
123 
124 		append(array, name, name_len, val, val_len);
125 	}
126 
127 	return 0;
128 }
129 
130 #endif
131