xref: /freebsd/lib/libiscsiutil/keys.c (revision fd99905b4591a5e4df3dda32e4c67258aaf44517)
163783933SJohn Baldwin /*-
263783933SJohn Baldwin  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
363783933SJohn Baldwin  *
463783933SJohn Baldwin  * Copyright (c) 2012 The FreeBSD Foundation
563783933SJohn Baldwin  *
663783933SJohn Baldwin  * This software was developed by Edward Tomasz Napierala under sponsorship
763783933SJohn Baldwin  * from the FreeBSD Foundation.
863783933SJohn Baldwin  *
963783933SJohn Baldwin  * Redistribution and use in source and binary forms, with or without
1063783933SJohn Baldwin  * modification, are permitted provided that the following conditions
1163783933SJohn Baldwin  * are met:
1263783933SJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
1363783933SJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
1463783933SJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
1563783933SJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
1663783933SJohn Baldwin  *    documentation and/or other materials provided with the distribution.
1763783933SJohn Baldwin  *
1863783933SJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1963783933SJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2063783933SJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2163783933SJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2263783933SJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2363783933SJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2463783933SJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2563783933SJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2663783933SJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2763783933SJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2863783933SJohn Baldwin  * SUCH DAMAGE.
2963783933SJohn Baldwin  */
3063783933SJohn Baldwin 
3163783933SJohn Baldwin #include <assert.h>
3263783933SJohn Baldwin #include <stdio.h>
3363783933SJohn Baldwin #include <stdlib.h>
3463783933SJohn Baldwin #include <string.h>
3563783933SJohn Baldwin 
3663783933SJohn Baldwin #include "libiscsiutil.h"
3763783933SJohn Baldwin 
3863783933SJohn Baldwin struct keys *
3963783933SJohn Baldwin keys_new(void)
4063783933SJohn Baldwin {
4163783933SJohn Baldwin 	struct keys *keys;
4263783933SJohn Baldwin 
4363783933SJohn Baldwin 	keys = calloc(1, sizeof(*keys));
4463783933SJohn Baldwin 	if (keys == NULL)
4563783933SJohn Baldwin 		log_err(1, "calloc");
4663783933SJohn Baldwin 
4763783933SJohn Baldwin 	return (keys);
4863783933SJohn Baldwin }
4963783933SJohn Baldwin 
5063783933SJohn Baldwin void
5163783933SJohn Baldwin keys_delete(struct keys *keys)
5263783933SJohn Baldwin {
5363783933SJohn Baldwin 
54*fd99905bSJohn Baldwin 	for (int i = 0; i < KEYS_MAX; i++) {
55*fd99905bSJohn Baldwin 		free(keys->keys_names[i]);
56*fd99905bSJohn Baldwin 		free(keys->keys_values[i]);
57*fd99905bSJohn Baldwin 	}
5863783933SJohn Baldwin 	free(keys);
5963783933SJohn Baldwin }
6063783933SJohn Baldwin 
6163783933SJohn Baldwin void
6263783933SJohn Baldwin keys_load(struct keys *keys, const struct pdu *pdu)
6363783933SJohn Baldwin {
6463783933SJohn Baldwin 	int i;
65*fd99905bSJohn Baldwin 	char *keys_data, *name, *pair, *value;
6663783933SJohn Baldwin 	size_t pair_len;
6763783933SJohn Baldwin 
6863783933SJohn Baldwin 	if (pdu->pdu_data_len == 0)
6963783933SJohn Baldwin 		return;
7063783933SJohn Baldwin 
7163783933SJohn Baldwin 	if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0')
7263783933SJohn Baldwin 		log_errx(1, "protocol error: key not NULL-terminated\n");
7363783933SJohn Baldwin 
74*fd99905bSJohn Baldwin 	keys_data = malloc(pdu->pdu_data_len);
75*fd99905bSJohn Baldwin 	if (keys_data == NULL)
7663783933SJohn Baldwin 		log_err(1, "malloc");
77*fd99905bSJohn Baldwin 	memcpy(keys_data, pdu->pdu_data, pdu->pdu_data_len);
7863783933SJohn Baldwin 
7963783933SJohn Baldwin 	/*
8063783933SJohn Baldwin 	 * XXX: Review this carefully.
8163783933SJohn Baldwin 	 */
82*fd99905bSJohn Baldwin 	pair = keys_data;
8363783933SJohn Baldwin 	for (i = 0;; i++) {
8463783933SJohn Baldwin 		if (i >= KEYS_MAX)
8563783933SJohn Baldwin 			log_errx(1, "too many keys received");
8663783933SJohn Baldwin 
8763783933SJohn Baldwin 		pair_len = strlen(pair);
8863783933SJohn Baldwin 
89*fd99905bSJohn Baldwin 		value = pair;
90*fd99905bSJohn Baldwin 		name = strsep(&value, "=");
91*fd99905bSJohn Baldwin 		if (name == NULL || value == NULL)
9263783933SJohn Baldwin 			log_errx(1, "malformed keys");
93*fd99905bSJohn Baldwin 		keys->keys_names[i] = checked_strdup(name);
94*fd99905bSJohn Baldwin 		keys->keys_values[i] = checked_strdup(value);
9563783933SJohn Baldwin 		log_debugx("key received: \"%s=%s\"",
9663783933SJohn Baldwin 		    keys->keys_names[i], keys->keys_values[i]);
9763783933SJohn Baldwin 
9863783933SJohn Baldwin 		pair += pair_len + 1; /* +1 to skip the terminating '\0'. */
99*fd99905bSJohn Baldwin 		if (pair == keys_data + pdu->pdu_data_len)
10063783933SJohn Baldwin 			break;
101*fd99905bSJohn Baldwin 		assert(pair < keys_data + pdu->pdu_data_len);
10263783933SJohn Baldwin 	}
103*fd99905bSJohn Baldwin 	free(keys_data);
10463783933SJohn Baldwin }
10563783933SJohn Baldwin 
10663783933SJohn Baldwin void
10763783933SJohn Baldwin keys_save(struct keys *keys, struct pdu *pdu)
10863783933SJohn Baldwin {
10963783933SJohn Baldwin 	char *data;
11063783933SJohn Baldwin 	size_t len;
11163783933SJohn Baldwin 	int i;
11263783933SJohn Baldwin 
11363783933SJohn Baldwin 	/*
11463783933SJohn Baldwin 	 * XXX: Not particularly efficient.
11563783933SJohn Baldwin 	 */
11663783933SJohn Baldwin 	len = 0;
11763783933SJohn Baldwin 	for (i = 0; i < KEYS_MAX; i++) {
11863783933SJohn Baldwin 		if (keys->keys_names[i] == NULL)
11963783933SJohn Baldwin 			break;
12063783933SJohn Baldwin 		/*
12163783933SJohn Baldwin 		 * +1 for '=', +1 for '\0'.
12263783933SJohn Baldwin 		 */
12363783933SJohn Baldwin 		len += strlen(keys->keys_names[i]) +
12463783933SJohn Baldwin 		    strlen(keys->keys_values[i]) + 2;
12563783933SJohn Baldwin 	}
12663783933SJohn Baldwin 
12763783933SJohn Baldwin 	if (len == 0)
12863783933SJohn Baldwin 		return;
12963783933SJohn Baldwin 
13063783933SJohn Baldwin 	data = malloc(len);
13163783933SJohn Baldwin 	if (data == NULL)
13263783933SJohn Baldwin 		log_err(1, "malloc");
13363783933SJohn Baldwin 
13463783933SJohn Baldwin 	pdu->pdu_data = data;
13563783933SJohn Baldwin 	pdu->pdu_data_len = len;
13663783933SJohn Baldwin 
13763783933SJohn Baldwin 	for (i = 0; i < KEYS_MAX; i++) {
13863783933SJohn Baldwin 		if (keys->keys_names[i] == NULL)
13963783933SJohn Baldwin 			break;
14063783933SJohn Baldwin 		data += sprintf(data, "%s=%s",
14163783933SJohn Baldwin 		    keys->keys_names[i], keys->keys_values[i]);
14263783933SJohn Baldwin 		data += 1; /* for '\0'. */
14363783933SJohn Baldwin 	}
14463783933SJohn Baldwin }
14563783933SJohn Baldwin 
14663783933SJohn Baldwin const char *
14763783933SJohn Baldwin keys_find(struct keys *keys, const char *name)
14863783933SJohn Baldwin {
14963783933SJohn Baldwin 	int i;
15063783933SJohn Baldwin 
15163783933SJohn Baldwin 	/*
15263783933SJohn Baldwin 	 * Note that we don't handle duplicated key names here,
15363783933SJohn Baldwin 	 * as they are not supposed to happen in requests, and if they do,
15463783933SJohn Baldwin 	 * it's an initiator error.
15563783933SJohn Baldwin 	 */
15663783933SJohn Baldwin 	for (i = 0; i < KEYS_MAX; i++) {
15763783933SJohn Baldwin 		if (keys->keys_names[i] == NULL)
15863783933SJohn Baldwin 			return (NULL);
15963783933SJohn Baldwin 		if (strcmp(keys->keys_names[i], name) == 0)
16063783933SJohn Baldwin 			return (keys->keys_values[i]);
16163783933SJohn Baldwin 	}
16263783933SJohn Baldwin 	return (NULL);
16363783933SJohn Baldwin }
16463783933SJohn Baldwin 
16563783933SJohn Baldwin void
16663783933SJohn Baldwin keys_add(struct keys *keys, const char *name, const char *value)
16763783933SJohn Baldwin {
16863783933SJohn Baldwin 	int i;
16963783933SJohn Baldwin 
17063783933SJohn Baldwin 	log_debugx("key to send: \"%s=%s\"", name, value);
17163783933SJohn Baldwin 
17263783933SJohn Baldwin 	/*
17363783933SJohn Baldwin 	 * Note that we don't check for duplicates here, as they are perfectly
17463783933SJohn Baldwin 	 * fine in responses, e.g. the "TargetName" keys in discovery sesion
17563783933SJohn Baldwin 	 * response.
17663783933SJohn Baldwin 	 */
17763783933SJohn Baldwin 	for (i = 0; i < KEYS_MAX; i++) {
17863783933SJohn Baldwin 		if (keys->keys_names[i] == NULL) {
17963783933SJohn Baldwin 			keys->keys_names[i] = checked_strdup(name);
18063783933SJohn Baldwin 			keys->keys_values[i] = checked_strdup(value);
18163783933SJohn Baldwin 			return;
18263783933SJohn Baldwin 		}
18363783933SJohn Baldwin 	}
18463783933SJohn Baldwin 	log_errx(1, "too many keys");
18563783933SJohn Baldwin }
18663783933SJohn Baldwin 
18763783933SJohn Baldwin void
18863783933SJohn Baldwin keys_add_int(struct keys *keys, const char *name, int value)
18963783933SJohn Baldwin {
19063783933SJohn Baldwin 	char *str;
19163783933SJohn Baldwin 	int ret;
19263783933SJohn Baldwin 
19363783933SJohn Baldwin 	ret = asprintf(&str, "%d", value);
19463783933SJohn Baldwin 	if (ret <= 0)
19563783933SJohn Baldwin 		log_err(1, "asprintf");
19663783933SJohn Baldwin 
19763783933SJohn Baldwin 	keys_add(keys, name, str);
19863783933SJohn Baldwin 	free(str);
19963783933SJohn Baldwin }
200