keys.c revision 270888
167754Smsmith/*- 267754Smsmith * Copyright (c) 2012 The FreeBSD Foundation 370243Smsmith * All rights reserved. 467754Smsmith * 567754Smsmith * This software was developed by Edward Tomasz Napierala under sponsorship 667754Smsmith * from the FreeBSD Foundation. 7217365Sjkim * 8306536Sjkim * Redistribution and use in source and binary forms, with or without 970243Smsmith * modification, are permitted provided that the following conditions 1067754Smsmith * are met: 11217365Sjkim * 1. Redistributions of source code must retain the above copyright 12217365Sjkim * notice, this list of conditions and the following disclaimer. 13217365Sjkim * 2. Redistributions in binary form must reproduce the above copyright 14217365Sjkim * notice, this list of conditions and the following disclaimer in the 15217365Sjkim * documentation and/or other materials provided with the distribution. 16217365Sjkim * 17217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18217365Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19217365Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20217365Sjkim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21217365Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2567754Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26217365Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27217365Sjkim * SUCH DAMAGE. 28217365Sjkim * 2967754Smsmith */ 30217365Sjkim 31217365Sjkim#include <sys/cdefs.h> 32217365Sjkim__FBSDID("$FreeBSD: stable/10/usr.sbin/iscsid/keys.c 270888 2014-08-31 20:21:08Z trasz $"); 33217365Sjkim 34217365Sjkim#include <assert.h> 35217365Sjkim#include <stdint.h> 36217365Sjkim#include <stdio.h> 37217365Sjkim#include <stdlib.h> 38217365Sjkim#include <string.h> 39217365Sjkim 40217365Sjkim#include "iscsid.h" 41217365Sjkim 42217365Sjkimstruct keys * 4367754Smsmithkeys_new(void) 4467754Smsmith{ 4567754Smsmith struct keys *keys; 4667754Smsmith 47193267Sjkim keys = calloc(sizeof(*keys), 1); 48193267Sjkim if (keys == NULL) 49306536Sjkim log_err(1, "calloc"); 50193267Sjkim 51231844Sjkim return (keys); 52193341Sjkim} 53193341Sjkim 54239340Sjkimvoid 5567754Smsmithkeys_delete(struct keys *keys) 56281075Sdim{ 57281075Sdim 58281075Sdim free(keys->keys_data); 59281075Sdim free(keys); 60281075Sdim} 61281075Sdim 62281075Sdimvoid 63193267Sjkimkeys_load(struct keys *keys, const struct pdu *pdu) 64281075Sdim{ 65281075Sdim int i; 66281075Sdim char *pair; 67281075Sdim size_t pair_len; 68193267Sjkim 69281075Sdim if (pdu->pdu_data_len == 0) 70281075Sdim return; 71281075Sdim 72281075Sdim if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0') 7377424Smsmith log_errx(1, "protocol error: key not NULL-terminated\n"); 74281075Sdim 75281075Sdim assert(keys->keys_data == NULL); 76193267Sjkim keys->keys_data_len = pdu->pdu_data_len; 77281075Sdim keys->keys_data = malloc(keys->keys_data_len); 78281075Sdim if (keys->keys_data == NULL) 79281075Sdim log_err(1, "malloc"); 80281075Sdim memcpy(keys->keys_data, pdu->pdu_data, keys->keys_data_len); 81281075Sdim 82193267Sjkim /* 83281075Sdim * XXX: Review this carefully. 84281075Sdim */ 85281075Sdim pair = keys->keys_data; 86281075Sdim for (i = 0;; i++) { 87281075Sdim if (i >= KEYS_MAX) 88193267Sjkim log_errx(1, "too many keys received"); 89281075Sdim 90281075Sdim pair_len = strlen(pair); 91281075Sdim 92281075Sdim keys->keys_values[i] = pair; 93281075Sdim keys->keys_names[i] = strsep(&keys->keys_values[i], "="); 94281075Sdim if (keys->keys_names[i] == NULL || keys->keys_values[i] == NULL) 95281075Sdim log_errx(1, "malformed keys"); 96281075Sdim log_debugx("key received: \"%s=%s\"", 97281075Sdim keys->keys_names[i], keys->keys_values[i]); 98193267Sjkim 99281075Sdim pair += pair_len + 1; /* +1 to skip the terminating '\0'. */ 100281075Sdim if (pair == keys->keys_data + keys->keys_data_len) 101281075Sdim break; 102281075Sdim assert(pair < keys->keys_data + keys->keys_data_len); 103193267Sjkim } 104281075Sdim} 105281075Sdim 106281075Sdimvoid 107281075Sdimkeys_save(struct keys *keys, struct pdu *pdu) 108281075Sdim{ 109281075Sdim char *data; 110281075Sdim size_t len; 111281075Sdim int i; 112281075Sdim 113281075Sdim /* 114281075Sdim * XXX: Not particularly efficient. 115281075Sdim */ 116281075Sdim len = 0; 117281075Sdim for (i = 0; i < KEYS_MAX; i++) { 118281075Sdim if (keys->keys_names[i] == NULL) 119281075Sdim break; 120281075Sdim /* 121281075Sdim * +1 for '=', +1 for '\0'. 122281075Sdim */ 123281075Sdim len += strlen(keys->keys_names[i]) + 124281075Sdim strlen(keys->keys_values[i]) + 2; 125281075Sdim } 126151937Sjkim 127281075Sdim if (len == 0) 128281075Sdim return; 129281075Sdim 130281075Sdim data = malloc(len); 131281075Sdim if (data == NULL) 132281075Sdim log_err(1, "malloc"); 133281075Sdim 134281075Sdim pdu->pdu_data = data; 135281075Sdim pdu->pdu_data_len = len; 136281075Sdim 137281075Sdim for (i = 0; i < KEYS_MAX; i++) { 138281075Sdim if (keys->keys_names[i] == NULL) 139281075Sdim break; 140281075Sdim data += sprintf(data, "%s=%s", 141281075Sdim keys->keys_names[i], keys->keys_values[i]); 142281075Sdim data += 1; /* for '\0'. */ 143281075Sdim } 144281075Sdim} 145281075Sdim 146281075Sdimconst char * 147281075Sdimkeys_find(struct keys *keys, const char *name) 148281075Sdim{ 149281075Sdim int i; 150281075Sdim 151281075Sdim /* 152281075Sdim * Note that we don't handle duplicated key names here, 153281075Sdim * as they are not supposed to happen in requests, and if they do, 154281075Sdim * it's an initiator error. 155281075Sdim */ 156281075Sdim for (i = 0; i < KEYS_MAX; i++) { 157281075Sdim if (keys->keys_names[i] == NULL) 158281075Sdim return (NULL); 159281075Sdim if (strcmp(keys->keys_names[i], name) == 0) 160281075Sdim return (keys->keys_values[i]); 161281075Sdim } 162281075Sdim return (NULL); 163281075Sdim} 164281075Sdim 165281075Sdimint 166281075Sdimkeys_find_int(struct keys *keys, const char *name) 167281075Sdim{ 168281075Sdim const char *str; 169281075Sdim char *endptr; 170281075Sdim int num; 171281075Sdim 172281075Sdim str = keys_find(keys, name); 173281075Sdim if (str == NULL) 174281075Sdim return (-1); 175281075Sdim 176281075Sdim num = strtoul(str, &endptr, 10); 177281075Sdim if (*endptr != '\0') { 178281075Sdim log_debugx("invalid numeric value \"%s\"", str); 179281075Sdim return (-1); 180281075Sdim } 181281075Sdim 182281075Sdim return (num); 183281075Sdim} 184281075Sdim 185281075Sdimvoid 186281075Sdimkeys_add(struct keys *keys, const char *name, const char *value) 187281075Sdim{ 188281075Sdim int i; 189281075Sdim 190281075Sdim log_debugx("key to send: \"%s=%s\"", name, value); 191281075Sdim 192281075Sdim /* 193281075Sdim * Note that we don't check for duplicates here, as they are perfectly 194281075Sdim * fine in responses, e.g. the "TargetName" keys in discovery sesion 195306536Sjkim * response. 196306536Sjkim */ 197306536Sjkim for (i = 0; i < KEYS_MAX; i++) { 198306536Sjkim if (keys->keys_names[i] == NULL) { 199306536Sjkim keys->keys_names[i] = checked_strdup(name); 200281075Sdim keys->keys_values[i] = checked_strdup(value); 201281075Sdim return; 202281075Sdim } 203281075Sdim } 204281075Sdim log_errx(1, "too many keys"); 205281075Sdim} 206281075Sdim 207281075Sdimvoid 208281075Sdimkeys_add_int(struct keys *keys, const char *name, int value) 209281075Sdim{ 210306536Sjkim char *str; 211306536Sjkim int ret; 212306536Sjkim 213306536Sjkim ret = asprintf(&str, "%d", value); 214306536Sjkim if (ret <= 0) 215306536Sjkim log_err(1, "asprintf"); 216306536Sjkim 217306536Sjkim keys_add(keys, name, str); 218306536Sjkim free(str); 219281075Sdim} 220281075Sdim