1255570Strasz/*- 2255570Strasz * Copyright (c) 2012 The FreeBSD Foundation 3255570Strasz * All rights reserved. 4255570Strasz * 5255570Strasz * This software was developed by Edward Tomasz Napierala under sponsorship 6255570Strasz * from the FreeBSD Foundation. 7255570Strasz * 8255570Strasz * Redistribution and use in source and binary forms, with or without 9255570Strasz * modification, are permitted provided that the following conditions 10255570Strasz * are met: 11255570Strasz * 1. Redistributions of source code must retain the above copyright 12255570Strasz * notice, this list of conditions and the following disclaimer. 13255570Strasz * 2. Redistributions in binary form must reproduce the above copyright 14255570Strasz * notice, this list of conditions and the following disclaimer in the 15255570Strasz * documentation and/or other materials provided with the distribution. 16255570Strasz * 17255570Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18255570Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19255570Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20255570Strasz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21255570Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22255570Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23255570Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24255570Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25255570Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26255570Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27255570Strasz * SUCH DAMAGE. 28255570Strasz * 29255570Strasz */ 30255570Strasz 31270888Strasz#include <sys/cdefs.h> 32270888Strasz__FBSDID("$FreeBSD: releng/10.2/usr.sbin/iscsid/keys.c 274870 2014-11-22 17:50:14Z trasz $"); 33270888Strasz 34255570Strasz#include <assert.h> 35255570Strasz#include <stdint.h> 36255570Strasz#include <stdio.h> 37255570Strasz#include <stdlib.h> 38255570Strasz#include <string.h> 39255570Strasz 40255570Strasz#include "iscsid.h" 41255570Strasz 42255570Straszstruct keys * 43255570Straszkeys_new(void) 44255570Strasz{ 45255570Strasz struct keys *keys; 46255570Strasz 47255570Strasz keys = calloc(sizeof(*keys), 1); 48255570Strasz if (keys == NULL) 49255570Strasz log_err(1, "calloc"); 50255570Strasz 51255570Strasz return (keys); 52255570Strasz} 53255570Strasz 54255570Straszvoid 55255570Straszkeys_delete(struct keys *keys) 56255570Strasz{ 57255570Strasz 58255570Strasz free(keys->keys_data); 59255570Strasz free(keys); 60255570Strasz} 61255570Strasz 62255570Straszvoid 63255570Straszkeys_load(struct keys *keys, const struct pdu *pdu) 64255570Strasz{ 65255570Strasz int i; 66255570Strasz char *pair; 67255570Strasz size_t pair_len; 68255570Strasz 69255570Strasz if (pdu->pdu_data_len == 0) 70262845Strasz return; 71255570Strasz 72255570Strasz if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0') 73255570Strasz log_errx(1, "protocol error: key not NULL-terminated\n"); 74255570Strasz 75255570Strasz assert(keys->keys_data == NULL); 76255570Strasz keys->keys_data_len = pdu->pdu_data_len; 77255570Strasz keys->keys_data = malloc(keys->keys_data_len); 78255570Strasz if (keys->keys_data == NULL) 79255570Strasz log_err(1, "malloc"); 80255570Strasz memcpy(keys->keys_data, pdu->pdu_data, keys->keys_data_len); 81255570Strasz 82255570Strasz /* 83255570Strasz * XXX: Review this carefully. 84255570Strasz */ 85255570Strasz pair = keys->keys_data; 86255570Strasz for (i = 0;; i++) { 87255570Strasz if (i >= KEYS_MAX) 88255570Strasz log_errx(1, "too many keys received"); 89255570Strasz 90255570Strasz pair_len = strlen(pair); 91255570Strasz 92255570Strasz keys->keys_values[i] = pair; 93255570Strasz keys->keys_names[i] = strsep(&keys->keys_values[i], "="); 94255570Strasz if (keys->keys_names[i] == NULL || keys->keys_values[i] == NULL) 95255570Strasz log_errx(1, "malformed keys"); 96255570Strasz log_debugx("key received: \"%s=%s\"", 97255570Strasz keys->keys_names[i], keys->keys_values[i]); 98255570Strasz 99255570Strasz pair += pair_len + 1; /* +1 to skip the terminating '\0'. */ 100255570Strasz if (pair == keys->keys_data + keys->keys_data_len) 101255570Strasz break; 102255570Strasz assert(pair < keys->keys_data + keys->keys_data_len); 103255570Strasz } 104255570Strasz} 105255570Strasz 106255570Straszvoid 107255570Straszkeys_save(struct keys *keys, struct pdu *pdu) 108255570Strasz{ 109255570Strasz char *data; 110255570Strasz size_t len; 111255570Strasz int i; 112255570Strasz 113255570Strasz /* 114255570Strasz * XXX: Not particularly efficient. 115255570Strasz */ 116255570Strasz len = 0; 117255570Strasz for (i = 0; i < KEYS_MAX; i++) { 118255570Strasz if (keys->keys_names[i] == NULL) 119255570Strasz break; 120274870Strasz /* 121255570Strasz * +1 for '=', +1 for '\0'. 122255570Strasz */ 123255570Strasz len += strlen(keys->keys_names[i]) + 124255570Strasz strlen(keys->keys_values[i]) + 2; 125255570Strasz } 126255570Strasz 127255570Strasz if (len == 0) 128255570Strasz return; 129255570Strasz 130255570Strasz data = malloc(len); 131255570Strasz if (data == NULL) 132255570Strasz log_err(1, "malloc"); 133255570Strasz 134255570Strasz pdu->pdu_data = data; 135255570Strasz pdu->pdu_data_len = len; 136255570Strasz 137255570Strasz for (i = 0; i < KEYS_MAX; i++) { 138255570Strasz if (keys->keys_names[i] == NULL) 139255570Strasz break; 140255570Strasz data += sprintf(data, "%s=%s", 141255570Strasz keys->keys_names[i], keys->keys_values[i]); 142255570Strasz data += 1; /* for '\0'. */ 143255570Strasz } 144255570Strasz} 145255570Strasz 146255570Straszconst char * 147255570Straszkeys_find(struct keys *keys, const char *name) 148255570Strasz{ 149255570Strasz int i; 150255570Strasz 151255570Strasz /* 152255570Strasz * Note that we don't handle duplicated key names here, 153255570Strasz * as they are not supposed to happen in requests, and if they do, 154255570Strasz * it's an initiator error. 155255570Strasz */ 156255570Strasz for (i = 0; i < KEYS_MAX; i++) { 157255570Strasz if (keys->keys_names[i] == NULL) 158255570Strasz return (NULL); 159255570Strasz if (strcmp(keys->keys_names[i], name) == 0) 160255570Strasz return (keys->keys_values[i]); 161255570Strasz } 162255570Strasz return (NULL); 163255570Strasz} 164255570Strasz 165255570Straszint 166255570Straszkeys_find_int(struct keys *keys, const char *name) 167255570Strasz{ 168255570Strasz const char *str; 169255570Strasz char *endptr; 170255570Strasz int num; 171255570Strasz 172255570Strasz str = keys_find(keys, name); 173255570Strasz if (str == NULL) 174255570Strasz return (-1); 175255570Strasz 176255570Strasz num = strtoul(str, &endptr, 10); 177255570Strasz if (*endptr != '\0') { 178255570Strasz log_debugx("invalid numeric value \"%s\"", str); 179255570Strasz return (-1); 180255570Strasz } 181255570Strasz 182255570Strasz return (num); 183255570Strasz} 184255570Strasz 185255570Straszvoid 186255570Straszkeys_add(struct keys *keys, const char *name, const char *value) 187255570Strasz{ 188255570Strasz int i; 189255570Strasz 190255570Strasz log_debugx("key to send: \"%s=%s\"", name, value); 191255570Strasz 192255570Strasz /* 193255570Strasz * Note that we don't check for duplicates here, as they are perfectly 194255570Strasz * fine in responses, e.g. the "TargetName" keys in discovery sesion 195255570Strasz * response. 196255570Strasz */ 197255570Strasz for (i = 0; i < KEYS_MAX; i++) { 198255570Strasz if (keys->keys_names[i] == NULL) { 199255570Strasz keys->keys_names[i] = checked_strdup(name); 200255570Strasz keys->keys_values[i] = checked_strdup(value); 201255570Strasz return; 202255570Strasz } 203255570Strasz } 204255570Strasz log_errx(1, "too many keys"); 205255570Strasz} 206255570Strasz 207255570Straszvoid 208255570Straszkeys_add_int(struct keys *keys, const char *name, int value) 209255570Strasz{ 210255570Strasz char *str; 211255570Strasz int ret; 212255570Strasz 213255570Strasz ret = asprintf(&str, "%d", value); 214255570Strasz if (ret <= 0) 215255570Strasz log_err(1, "asprintf"); 216255570Strasz 217255570Strasz keys_add(keys, name, str); 218255570Strasz free(str); 219255570Strasz} 220