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.3/usr.sbin/ctld/keys.c 288704 2015-10-05 07:42:05Z mav $"); 33270888Strasz 34255570Strasz#include <assert.h> 35255570Strasz#include <stdio.h> 36255570Strasz#include <stdlib.h> 37255570Strasz#include <string.h> 38255570Strasz#include "ctld.h" 39255570Strasz 40255570Straszstruct keys * 41255570Straszkeys_new(void) 42255570Strasz{ 43255570Strasz struct keys *keys; 44255570Strasz 45255570Strasz keys = calloc(sizeof(*keys), 1); 46255570Strasz if (keys == NULL) 47255570Strasz log_err(1, "calloc"); 48255570Strasz 49255570Strasz return (keys); 50255570Strasz} 51255570Strasz 52255570Straszvoid 53255570Straszkeys_delete(struct keys *keys) 54255570Strasz{ 55255570Strasz 56255570Strasz free(keys->keys_data); 57255570Strasz free(keys); 58255570Strasz} 59255570Strasz 60255570Straszvoid 61255570Straszkeys_load(struct keys *keys, const struct pdu *pdu) 62255570Strasz{ 63255570Strasz int i; 64255570Strasz char *pair; 65255570Strasz size_t pair_len; 66255570Strasz 67255570Strasz if (pdu->pdu_data_len == 0) 68263733Strasz return; 69255570Strasz 70255570Strasz if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0') 71255570Strasz log_errx(1, "protocol error: key not NULL-terminated\n"); 72255570Strasz 73255570Strasz assert(keys->keys_data == NULL); 74255570Strasz keys->keys_data_len = pdu->pdu_data_len; 75255570Strasz keys->keys_data = malloc(keys->keys_data_len); 76255570Strasz if (keys->keys_data == NULL) 77255570Strasz log_err(1, "malloc"); 78255570Strasz memcpy(keys->keys_data, pdu->pdu_data, keys->keys_data_len); 79255570Strasz 80255570Strasz /* 81255570Strasz * XXX: Review this carefully. 82255570Strasz */ 83255570Strasz pair = keys->keys_data; 84255570Strasz for (i = 0;; i++) { 85255570Strasz if (i >= KEYS_MAX) 86255570Strasz log_errx(1, "too many keys received"); 87255570Strasz 88255570Strasz pair_len = strlen(pair); 89255570Strasz 90255570Strasz keys->keys_values[i] = pair; 91255570Strasz keys->keys_names[i] = strsep(&keys->keys_values[i], "="); 92255570Strasz if (keys->keys_names[i] == NULL || keys->keys_values[i] == NULL) 93255570Strasz log_errx(1, "malformed keys"); 94255570Strasz log_debugx("key received: \"%s=%s\"", 95255570Strasz keys->keys_names[i], keys->keys_values[i]); 96255570Strasz 97255570Strasz pair += pair_len + 1; /* +1 to skip the terminating '\0'. */ 98255570Strasz if (pair == keys->keys_data + keys->keys_data_len) 99255570Strasz break; 100255570Strasz assert(pair < keys->keys_data + keys->keys_data_len); 101255570Strasz } 102255570Strasz} 103255570Strasz 104255570Straszvoid 105255570Straszkeys_save(struct keys *keys, struct pdu *pdu) 106255570Strasz{ 107255570Strasz char *data; 108255570Strasz size_t len; 109255570Strasz int i; 110255570Strasz 111255570Strasz /* 112255570Strasz * XXX: Not particularly efficient. 113255570Strasz */ 114255570Strasz len = 0; 115255570Strasz for (i = 0; i < KEYS_MAX; i++) { 116255570Strasz if (keys->keys_names[i] == NULL) 117255570Strasz break; 118274870Strasz /* 119255570Strasz * +1 for '=', +1 for '\0'. 120255570Strasz */ 121255570Strasz len += strlen(keys->keys_names[i]) + 122255570Strasz strlen(keys->keys_values[i]) + 2; 123255570Strasz } 124255570Strasz 125255570Strasz if (len == 0) 126255570Strasz return; 127255570Strasz 128255570Strasz data = malloc(len); 129255570Strasz if (data == NULL) 130255570Strasz log_err(1, "malloc"); 131255570Strasz 132255570Strasz pdu->pdu_data = data; 133255570Strasz pdu->pdu_data_len = len; 134255570Strasz 135255570Strasz for (i = 0; i < KEYS_MAX; i++) { 136255570Strasz if (keys->keys_names[i] == NULL) 137255570Strasz break; 138255570Strasz data += sprintf(data, "%s=%s", 139255570Strasz keys->keys_names[i], keys->keys_values[i]); 140255570Strasz data += 1; /* for '\0'. */ 141255570Strasz } 142255570Strasz} 143255570Strasz 144255570Straszconst char * 145255570Straszkeys_find(struct keys *keys, const char *name) 146255570Strasz{ 147255570Strasz int i; 148255570Strasz 149255570Strasz /* 150255570Strasz * Note that we don't handle duplicated key names here, 151255570Strasz * as they are not supposed to happen in requests, and if they do, 152255570Strasz * it's an initiator error. 153255570Strasz */ 154255570Strasz for (i = 0; i < KEYS_MAX; i++) { 155255570Strasz if (keys->keys_names[i] == NULL) 156255570Strasz return (NULL); 157255570Strasz if (strcmp(keys->keys_names[i], name) == 0) 158255570Strasz return (keys->keys_values[i]); 159255570Strasz } 160255570Strasz return (NULL); 161255570Strasz} 162255570Strasz 163255570Straszvoid 164255570Straszkeys_add(struct keys *keys, const char *name, const char *value) 165255570Strasz{ 166255570Strasz int i; 167255570Strasz 168255570Strasz log_debugx("key to send: \"%s=%s\"", name, value); 169255570Strasz 170255570Strasz /* 171255570Strasz * Note that we don't check for duplicates here, as they are perfectly 172255570Strasz * fine in responses, e.g. the "TargetName" keys in discovery sesion 173255570Strasz * response. 174255570Strasz */ 175255570Strasz for (i = 0; i < KEYS_MAX; i++) { 176255570Strasz if (keys->keys_names[i] == NULL) { 177255570Strasz keys->keys_names[i] = checked_strdup(name); 178255570Strasz keys->keys_values[i] = checked_strdup(value); 179255570Strasz return; 180255570Strasz } 181255570Strasz } 182255570Strasz log_errx(1, "too many keys"); 183255570Strasz} 184255570Strasz 185255570Straszvoid 186255570Straszkeys_add_int(struct keys *keys, const char *name, int value) 187255570Strasz{ 188255570Strasz char *str; 189255570Strasz int ret; 190255570Strasz 191255570Strasz ret = asprintf(&str, "%d", value); 192255570Strasz if (ret <= 0) 193255570Strasz log_err(1, "asprintf"); 194255570Strasz 195255570Strasz keys_add(keys, name, str); 196255570Strasz free(str); 197255570Strasz} 198