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