xref: /freebsd/lib/libiscsiutil/keys.c (revision 6378393308bc6bd81fb871dacf6b03cf1a390d8b)
1*63783933SJohn Baldwin /*-
2*63783933SJohn Baldwin  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*63783933SJohn Baldwin  *
4*63783933SJohn Baldwin  * Copyright (c) 2012 The FreeBSD Foundation
5*63783933SJohn Baldwin  *
6*63783933SJohn Baldwin  * This software was developed by Edward Tomasz Napierala under sponsorship
7*63783933SJohn Baldwin  * from the FreeBSD Foundation.
8*63783933SJohn Baldwin  *
9*63783933SJohn Baldwin  * Redistribution and use in source and binary forms, with or without
10*63783933SJohn Baldwin  * modification, are permitted provided that the following conditions
11*63783933SJohn Baldwin  * are met:
12*63783933SJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
13*63783933SJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
14*63783933SJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
15*63783933SJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
16*63783933SJohn Baldwin  *    documentation and/or other materials provided with the distribution.
17*63783933SJohn Baldwin  *
18*63783933SJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19*63783933SJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*63783933SJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*63783933SJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22*63783933SJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*63783933SJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*63783933SJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*63783933SJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*63783933SJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*63783933SJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*63783933SJohn Baldwin  * SUCH DAMAGE.
29*63783933SJohn Baldwin  */
30*63783933SJohn Baldwin 
31*63783933SJohn Baldwin #include <assert.h>
32*63783933SJohn Baldwin #include <stdio.h>
33*63783933SJohn Baldwin #include <stdlib.h>
34*63783933SJohn Baldwin #include <string.h>
35*63783933SJohn Baldwin 
36*63783933SJohn Baldwin #include "libiscsiutil.h"
37*63783933SJohn Baldwin 
38*63783933SJohn Baldwin struct keys *
39*63783933SJohn Baldwin keys_new(void)
40*63783933SJohn Baldwin {
41*63783933SJohn Baldwin 	struct keys *keys;
42*63783933SJohn Baldwin 
43*63783933SJohn Baldwin 	keys = calloc(1, sizeof(*keys));
44*63783933SJohn Baldwin 	if (keys == NULL)
45*63783933SJohn Baldwin 		log_err(1, "calloc");
46*63783933SJohn Baldwin 
47*63783933SJohn Baldwin 	return (keys);
48*63783933SJohn Baldwin }
49*63783933SJohn Baldwin 
50*63783933SJohn Baldwin void
51*63783933SJohn Baldwin keys_delete(struct keys *keys)
52*63783933SJohn Baldwin {
53*63783933SJohn Baldwin 
54*63783933SJohn Baldwin 	free(keys->keys_data);
55*63783933SJohn Baldwin 	free(keys);
56*63783933SJohn Baldwin }
57*63783933SJohn Baldwin 
58*63783933SJohn Baldwin void
59*63783933SJohn Baldwin keys_load(struct keys *keys, const struct pdu *pdu)
60*63783933SJohn Baldwin {
61*63783933SJohn Baldwin 	int i;
62*63783933SJohn Baldwin 	char *pair;
63*63783933SJohn Baldwin 	size_t pair_len;
64*63783933SJohn Baldwin 
65*63783933SJohn Baldwin 	if (pdu->pdu_data_len == 0)
66*63783933SJohn Baldwin 		return;
67*63783933SJohn Baldwin 
68*63783933SJohn Baldwin 	if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0')
69*63783933SJohn Baldwin 		log_errx(1, "protocol error: key not NULL-terminated\n");
70*63783933SJohn Baldwin 
71*63783933SJohn Baldwin 	assert(keys->keys_data == NULL);
72*63783933SJohn Baldwin 	keys->keys_data_len = pdu->pdu_data_len;
73*63783933SJohn Baldwin 	keys->keys_data = malloc(keys->keys_data_len);
74*63783933SJohn Baldwin 	if (keys->keys_data == NULL)
75*63783933SJohn Baldwin 		log_err(1, "malloc");
76*63783933SJohn Baldwin 	memcpy(keys->keys_data, pdu->pdu_data, keys->keys_data_len);
77*63783933SJohn Baldwin 
78*63783933SJohn Baldwin 	/*
79*63783933SJohn Baldwin 	 * XXX: Review this carefully.
80*63783933SJohn Baldwin 	 */
81*63783933SJohn Baldwin 	pair = keys->keys_data;
82*63783933SJohn Baldwin 	for (i = 0;; i++) {
83*63783933SJohn Baldwin 		if (i >= KEYS_MAX)
84*63783933SJohn Baldwin 			log_errx(1, "too many keys received");
85*63783933SJohn Baldwin 
86*63783933SJohn Baldwin 		pair_len = strlen(pair);
87*63783933SJohn Baldwin 
88*63783933SJohn Baldwin 		keys->keys_values[i] = pair;
89*63783933SJohn Baldwin 		keys->keys_names[i] = strsep(&keys->keys_values[i], "=");
90*63783933SJohn Baldwin 		if (keys->keys_names[i] == NULL || keys->keys_values[i] == NULL)
91*63783933SJohn Baldwin 			log_errx(1, "malformed keys");
92*63783933SJohn Baldwin 		log_debugx("key received: \"%s=%s\"",
93*63783933SJohn Baldwin 		    keys->keys_names[i], keys->keys_values[i]);
94*63783933SJohn Baldwin 
95*63783933SJohn Baldwin 		pair += pair_len + 1; /* +1 to skip the terminating '\0'. */
96*63783933SJohn Baldwin 		if (pair == keys->keys_data + keys->keys_data_len)
97*63783933SJohn Baldwin 			break;
98*63783933SJohn Baldwin 		assert(pair < keys->keys_data + keys->keys_data_len);
99*63783933SJohn Baldwin 	}
100*63783933SJohn Baldwin }
101*63783933SJohn Baldwin 
102*63783933SJohn Baldwin void
103*63783933SJohn Baldwin keys_save(struct keys *keys, struct pdu *pdu)
104*63783933SJohn Baldwin {
105*63783933SJohn Baldwin 	char *data;
106*63783933SJohn Baldwin 	size_t len;
107*63783933SJohn Baldwin 	int i;
108*63783933SJohn Baldwin 
109*63783933SJohn Baldwin 	/*
110*63783933SJohn Baldwin 	 * XXX: Not particularly efficient.
111*63783933SJohn Baldwin 	 */
112*63783933SJohn Baldwin 	len = 0;
113*63783933SJohn Baldwin 	for (i = 0; i < KEYS_MAX; i++) {
114*63783933SJohn Baldwin 		if (keys->keys_names[i] == NULL)
115*63783933SJohn Baldwin 			break;
116*63783933SJohn Baldwin 		/*
117*63783933SJohn Baldwin 		 * +1 for '=', +1 for '\0'.
118*63783933SJohn Baldwin 		 */
119*63783933SJohn Baldwin 		len += strlen(keys->keys_names[i]) +
120*63783933SJohn Baldwin 		    strlen(keys->keys_values[i]) + 2;
121*63783933SJohn Baldwin 	}
122*63783933SJohn Baldwin 
123*63783933SJohn Baldwin 	if (len == 0)
124*63783933SJohn Baldwin 		return;
125*63783933SJohn Baldwin 
126*63783933SJohn Baldwin 	data = malloc(len);
127*63783933SJohn Baldwin 	if (data == NULL)
128*63783933SJohn Baldwin 		log_err(1, "malloc");
129*63783933SJohn Baldwin 
130*63783933SJohn Baldwin 	pdu->pdu_data = data;
131*63783933SJohn Baldwin 	pdu->pdu_data_len = len;
132*63783933SJohn Baldwin 
133*63783933SJohn Baldwin 	for (i = 0; i < KEYS_MAX; i++) {
134*63783933SJohn Baldwin 		if (keys->keys_names[i] == NULL)
135*63783933SJohn Baldwin 			break;
136*63783933SJohn Baldwin 		data += sprintf(data, "%s=%s",
137*63783933SJohn Baldwin 		    keys->keys_names[i], keys->keys_values[i]);
138*63783933SJohn Baldwin 		data += 1; /* for '\0'. */
139*63783933SJohn Baldwin 	}
140*63783933SJohn Baldwin }
141*63783933SJohn Baldwin 
142*63783933SJohn Baldwin const char *
143*63783933SJohn Baldwin keys_find(struct keys *keys, const char *name)
144*63783933SJohn Baldwin {
145*63783933SJohn Baldwin 	int i;
146*63783933SJohn Baldwin 
147*63783933SJohn Baldwin 	/*
148*63783933SJohn Baldwin 	 * Note that we don't handle duplicated key names here,
149*63783933SJohn Baldwin 	 * as they are not supposed to happen in requests, and if they do,
150*63783933SJohn Baldwin 	 * it's an initiator error.
151*63783933SJohn Baldwin 	 */
152*63783933SJohn Baldwin 	for (i = 0; i < KEYS_MAX; i++) {
153*63783933SJohn Baldwin 		if (keys->keys_names[i] == NULL)
154*63783933SJohn Baldwin 			return (NULL);
155*63783933SJohn Baldwin 		if (strcmp(keys->keys_names[i], name) == 0)
156*63783933SJohn Baldwin 			return (keys->keys_values[i]);
157*63783933SJohn Baldwin 	}
158*63783933SJohn Baldwin 	return (NULL);
159*63783933SJohn Baldwin }
160*63783933SJohn Baldwin 
161*63783933SJohn Baldwin void
162*63783933SJohn Baldwin keys_add(struct keys *keys, const char *name, const char *value)
163*63783933SJohn Baldwin {
164*63783933SJohn Baldwin 	int i;
165*63783933SJohn Baldwin 
166*63783933SJohn Baldwin 	log_debugx("key to send: \"%s=%s\"", name, value);
167*63783933SJohn Baldwin 
168*63783933SJohn Baldwin 	/*
169*63783933SJohn Baldwin 	 * Note that we don't check for duplicates here, as they are perfectly
170*63783933SJohn Baldwin 	 * fine in responses, e.g. the "TargetName" keys in discovery sesion
171*63783933SJohn Baldwin 	 * response.
172*63783933SJohn Baldwin 	 */
173*63783933SJohn Baldwin 	for (i = 0; i < KEYS_MAX; i++) {
174*63783933SJohn Baldwin 		if (keys->keys_names[i] == NULL) {
175*63783933SJohn Baldwin 			keys->keys_names[i] = checked_strdup(name);
176*63783933SJohn Baldwin 			keys->keys_values[i] = checked_strdup(value);
177*63783933SJohn Baldwin 			return;
178*63783933SJohn Baldwin 		}
179*63783933SJohn Baldwin 	}
180*63783933SJohn Baldwin 	log_errx(1, "too many keys");
181*63783933SJohn Baldwin }
182*63783933SJohn Baldwin 
183*63783933SJohn Baldwin void
184*63783933SJohn Baldwin keys_add_int(struct keys *keys, const char *name, int value)
185*63783933SJohn Baldwin {
186*63783933SJohn Baldwin 	char *str;
187*63783933SJohn Baldwin 	int ret;
188*63783933SJohn Baldwin 
189*63783933SJohn Baldwin 	ret = asprintf(&str, "%d", value);
190*63783933SJohn Baldwin 	if (ret <= 0)
191*63783933SJohn Baldwin 		log_err(1, "asprintf");
192*63783933SJohn Baldwin 
193*63783933SJohn Baldwin 	keys_add(keys, name, str);
194*63783933SJohn Baldwin 	free(str);
195*63783933SJohn Baldwin }
196