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